Grep, regex या perl के साथ एक पैटर्न के बाद स्ट्रिंग कैसे निकालें


90

मेरे पास एक फाइल है जो कुछ इस तरह दिखती है:

    <table name="content_analyzer" primary-key="id">
      <type="global" />
    </table>
    <table name="content_analyzer2" primary-key="id">
      <type="global" />
    </table>
    <table name="content_analyzer_items" primary-key="id">
      <type="global" />
    </table>

मुझे उद्धरणों के भीतर कुछ भी निकालने की ज़रूरत है name=, अर्थात content_analyzer, content_analyzer2और content_analyzer_items

मैं एक लिनक्स बॉक्स पर ऐसा कर रहा हूं, इसलिए sed, perl, grep या bash का उपयोग करने वाला समाधान ठीक है।


5
शर्म करने की ज़रूरत नहीं है, यहाँ आपका स्वागत है!
बेनोइट

8
मुझे लगता है कि stackoverflow.com/questions/1732348/…
Christoffer Hammarström

उपयोगी टिप्पणियों के लिए सभी को धन्यवाद। मैं XML के लिए ठीक से फॉर्मेट नहीं किए जाने के लिए माफी मांगता हूं। मैंने सरलीकरण के लिए कुछ टैग हटा दिए हैं।
रैंगलर

जवाबों:


167

चूंकि आपको परिणाम में इसे शामिल किए बिना सामग्री का मिलान करने की आवश्यकता है (मिलान करना चाहिए, name=" लेकिन यह वांछित परिणाम का हिस्सा नहीं है) शून्य-चौड़ाई मिलान या समूह कैप्चरिंग के कुछ रूप की आवश्यकता है। यह निम्नलिखित उपकरणों के साथ आसानी से किया जा सकता है:

पर्ल

पर्ल के साथ आप n लाइन से लूप लाइन के विकल्प का उपयोग कर सकते हैं और यदि यह मेल खाता है तो कैप्चरिंग ग्रुप की सामग्री प्रिंट कर सकते हैं:

perl -ne 'print "$1\n" if /name="(.*?)"/' filename

ग्नू ग्रीप

यदि आपके पास grep का उन्नत संस्करण है, जैसे GNU grep, तो आपके पास -Pविकल्प उपलब्ध हो सकता है । यह विकल्प पर्ल- \Kलाइक रेगेक्स को सक्षम करेगा, जिससे आप उपयोग कर सकते हैं जो शॉर्टहैंड लुकहैंड है। यह मैच की स्थिति को रीसेट कर देगा, इसलिए शून्य-चौड़ाई से पहले कुछ भी।

grep -Po 'name="\K.*?(?=")' filename

o विकल्प बनाता है ग्रेप पूरी लाइन के स्थान पर केवल मिलान वाला पाठ मुद्रित करते है।

विम - पाठ संपादक

एक अन्य तरीका सीधे एक टेक्स्ट एडिटर का उपयोग करना है। विम के साथ, इसे पूरा करने के विभिन्न तरीकों में से एक बिना लाइनों को हटाना name=और फिर परिणामी लाइनों से सामग्री निकालना होगा:

:v/.*name="\v([^"]+).*/d|%s//\1

मानक grep

यदि आपके पास इन उपकरणों तक पहुंच नहीं है, तो किसी कारण से, मानक grep के साथ कुछ समान हासिल किया जा सकता है। हालांकि, इसके चारों ओर देखने के बिना बाद में कुछ सफाई की आवश्यकता होगी:

grep -o 'name="[^"]*"' filename

परिणामों को सहेजने के बारे में एक नोट

परिणामों के ऊपर सभी आदेशों में भेजा जाएगा stdout। यह याद रखना महत्वपूर्ण है कि आप उन्हें फ़ाइल में जोड़कर हमेशा बचा सकते हैं:

> result

कमांड के अंत में।


12
लुकरॉइड्स (GNU में grep):grep -Po '.*name="\K.*?(?=".*)'
अगली सूचना तक

@ डेनिस विलियमसन, महान। मैंने उसके अनुसार उत्तर को अपडेट किया, लेकिन दोनों .*को छोड़ दिया, मुझे आशा है कि आप मुझसे नाराज नहीं होंगे। मैं पूछना चाहता हूं, क्या आपको "कुछ भी छोड़कर "" से अधिक लालची मैच से कोई लाभ दिखाई देता है ? इसे एक लड़ाई के रूप में न लें, मैं सिर्फ जिज्ञासु हूं और मैं रेगेक्स विशेषज्ञ नहीं हूं। इसके अलावा, \Kटिप, वास्तव में अच्छा है। धन्यवाद डेनिस।
sidyll

2
मैं क्यों नाराज होऊंगा? बिना .*आप कर सकते हैं grep -Po '(?<=name=").*?(?=")'\Kआशुलिपि के लिए इस्तेमाल किया जा सकता है, लेकिन यह वास्तव में केवल आवश्यक है, अगर उसके बाईं ओर मैच चर लंबाई है। इस तरह के मामलों में, लुकरॉइड्स का उपयोग करने का कारण काफी स्पष्ट है। अस्वास्थ्यकर संचालन थोड़ा नटखट दिखता है ( [^"]*बनाम .*?और आपको एंकर के चरित्र को दोहराना नहीं है। मुझे गति के बारे में पता नहीं है। यह संदर्भ पर बहुत कुछ निर्भर करता है, मुझे लगता है। मुझे आशा है कि यह मददगार है।
आगे की सूचना तक रोका गया।

@ डेनिस विलियमसन: निश्चित रूप से साहब, यहाँ बहुत सारी उपयोगी जानकारी। मुझे लगता है कि इसका कारण मैंने \K(इस पर शोध के बाद) रखा और .*वही हटा दिया : इसे सुंदर (सरल) बना दें। और मैंने .*?"पारंपरिक तरीके" के बजाय उपयोग करने के बारे में कभी नहीं सोचा था जो मैंने कहीं से सीखा है। लेकिन यहाँ गैर-लालची वास्तव में समझ में आता है। धन्यवाद डेनिस, शुभकामनाएं।
शनिवार

कमांड का वर्णन करने के लिए +1। यदि आप रेगेक्स के "[...]" भाग को समझाने के लिए अपने उत्तर को अपडेट कर सकते हैं तो इसकी सराहना करेंगे।
16 मई को प्रजनक


5

यदि आप पर्ल का उपयोग कर रहे हैं, तो XML को पार्स करने के लिए एक मॉड्यूल डाउनलोड करें: XML :: सरल , XML :: टहनी , या XML :: LibXML । पहिया का फिर से आविष्कार न करें।


3
ध्यान दें कि ओपी ने जो उदाहरण दिया है वह अच्छी तरह से नहीं बना है ( <type="global"उदाहरण के लिए), इसलिए अधिकांश XML पार्सर सिर्फ शिकायत करते हैं और मर जाते हैं।
bvr

5

एक HTML पार्सर का उपयोग नियमित अभिव्यक्तियों के बजाय इस उद्देश्य के लिए किया जाना चाहिए। एक पर्ल प्रोग्राम जो इसका उपयोग करता हैHTML::TreeBuilder :

कार्यक्रम

#!/usr/bin/env perl

use strict;
use warnings;

use HTML::TreeBuilder;

my $tree = HTML::TreeBuilder->new_from_file( \*DATA );
my @elements = $tree->look_down(
    sub { defined $_[0]->attr('name') }
);

for (@elements) {
    print $_->attr('name'), "\n";
}

__DATA__
<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

उत्पादन

content_analyzer
content_analyzer2
content_analyzer_items


2

यहाँ HTML सुव्यवस्थित और xmlstarlet का उपयोग कर समाधान दिया गया है:

htmlstr='
<table name="content_analyzer" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
<type="global" />
</table>
'

echo "$htmlstr" | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
sed '/type="global"/d' |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

1

ओह, सेड कमांड को निश्चित रूप से सुव्यवस्थित कमांड से पहले जाना है:

echo "$htmlstr" | 
sed '/type="global"/d' |
tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

0

यदि आपके xml (या सामान्य रूप से पाठ) की संरचना तय हो गई है, तो सबसे आसान तरीका उपयोग कर रहा है cut। आपके विशिष्ट मामले के लिए:

echo '<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>' | grep name= | cut -f2 -d '"'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.