गैर लालची (अनिच्छुक) रेगीक्स सेड में मेल?


406

मैं केवल डोमेन निकालने के लिए URL की पंक्तियों को साफ करने के लिए sed का उपयोग करने की कोशिश कर रहा हूं।

तो इससे:

http://www.suepearson.co.uk/product/174/71/3816/

मुझे चाहिए:

http://www.suepearson.co.uk/

(या तो अनुगामी स्लैश के साथ या इसके बिना, कोई फर्क नहीं पड़ता)

मैंने कोशिश की है:

 sed 's|\(http:\/\/.*?\/\).*|\1|'

और (गैर-लालची क्वांटिफायर से बचकर)

sed 's|\(http:\/\/.*\?\/\).*|\1|'

लेकिन मुझे काम करने के लिए गैर-लालची मात्रात्मक ( ?) प्राप्त करने के लिए प्रतीत नहीं हो सकता है , इसलिए यह हमेशा पूरे स्ट्रिंग से मेल खाता है।


54
एक साइड-नोट: यदि आप अपने रेगीक्स को "|" के साथ सीमांकित करते हैं, तो आपको "/" s से बचने की आवश्यकता नहीं है। वास्तव में, ज्यादातर लोग "|" "/" के बजाय "पिकेट की बाड़" से बचने के लिए।
AttishOculus

12
@AttishOculus सेड में स्थानापन्न अभिव्यक्ति में 's' के बाद पहला चरित्र सीमांकक है। इसलिए 'एस ^ फू ^ बार' या 'एस! फू! बार!' यह भी काम
स्क्वीडली

1
विस्तारित रेगेक्स के लिए, उपयोग करें sed -E 's...। फिर भी, कोई अनिच्छुक ऑपरेटर नहीं।
ओंद्र kaयूका

प्रश्न शीर्षक का जवाब नहीं है लेकिन इस विशिष्ट मामले में सरल cut -d'/' -f1-3काम करता है।
पेट्र जवोरिक

जवाबों:


421

न तो मूल और न ही विस्तारित पॉज़िक्स / जीएनयू रेगेक्स गैर-लालची क्वांटिफायर को पहचानता है; आपको बाद में regex की आवश्यकता है। सौभाग्य से, इस संदर्भ के लिए पर्ल रेगेक्स प्राप्त करना बहुत आसान है:

perl -pe 's|(http://.*?/).*|\1|'

12
जगह के उपयोग के विकल्पों में इसे करने के लिए -pi -e
वास्तव में

11
पवित्र धूम्रपान मैं विश्वास नहीं कर सकता कि काम किया :-) केवल एक चीज जो चूसती है अब मेरी स्क्रिप्ट में एक पर्ल निर्भरता है :-( प्लस तरफ, वस्तुतः हर लिनक्स डिस्ट्रो के पास पर्ल पहले से ही है इसलिए शायद यह मुद्दा नहीं है :-)
Freedom_Ben

6
@Freedom_Ben: IIRC perlको POSIX
MestreLion

4
@ dolphus333: "न तो बेसिक और न ही विस्तारित पॉज़िक्स / GNU रेगेक्स गैर-लालची क्वांटिफायर को पहचानता है" का अर्थ है "आप गैर-लालची क्वांटिफायर का उपयोग नहीं कर सकते हैं"।
अराजकता

3
@ Sérgio यह है कि आप अनुरोधित चीज़ को कैसे करते हैं, जो कि असंभव है sed, एक सिंटैक्स का उपयोग करना मूल रूप से समान हैsed
अराजकता

250

इस विशिष्ट मामले में, आप गैर-लालची रेगेक्स का उपयोग किए बिना काम पा सकते हैं।

[^/]*इसके बजाय इस गैर-लालची regex का प्रयास करें .*?:

sed 's|\(http://[^/]*/\).*|\1|g'

3
इस तकनीक का उपयोग करके सेड मैच को गैर लालची एक वाक्यांश कैसे बनाया जाए?
14:36 ​​पर user3694243

6
दुर्भाग्य से आप नहीं कर सकते; अराजकता का जवाब देखें ।
डैनियल एच

बहुत धन्यवाद ... चूंकि पर्ल कई लिनक्स डिस्ट्रो में डिफॉल्ट इंस्टॉलेशन बेस में नहीं है!
st0ne


@ डैनियल वास्तव में अनुरोध के अनुसार इस तकनीक का उपयोग करके गैर-लालची वाक्यांशों का मिलान करना संभव है । बस पर्याप्त सटीकता के साथ पैटर्न लिखने के लिए कुछ दर्द हो सकता है। उदाहरण के लिए, URL की क्वेरी में कुंजी-मान असाइनमेंट पार्स करते समय इसका उपयोग करके असाइनमेंट की खोज करने की आवश्यकता हो सकती है ([^&=#]+)=([^&#]*)। ऐसे मामले हैं जो सुनिश्चित करने के लिए इस तरह से काम नहीं करते हैं, उदाहरण के लिए जब अपने मेजबान भाग के लिए यूआरएल और अंतिम स्लैश के साथ मार्गनाम को कैप्चरिंग से बाहर रखा जाना वैकल्पिक माना जाता है:^(http:\/\/.+?)/?$
थॉमस अर्बन

121

सीड के साथ, मैं आमतौर पर विभाजक को छोड़कर विभाजक को छोड़कर कुछ भी खोज करके गैर-लालची खोज को लागू करता हूं:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'

आउटपुट:

http://www.suon.co.uk

ये है:

  • आउटपुट नहीं -n
  • खोज, मिलान पैटर्न, बदलें और प्रिंट करें s/<pattern>/<replace>/p
  • के ;बजाय खोज कमांड विभाजक का उपयोग करें/ इसे टाइप करना आसान बनाने लिएs;<pattern>;<replace>;p
  • कोष्ठक के बीच मैच याद रखें \( ... \), बाद में \1,\2 ...
  • मेल खाते हैं http://
  • कोष्ठक में कुछ भी द्वारा पीछा किया [],[ab/]a या तो मतलब होगा bया/
  • प्रथम ^ में []साधनnot है, इसलिए कुछ भी द्वारा पीछा किया लेकिन में बात[]
  • इसलिए [^/]सिवाय कुछ भी मतलब है/ चरित्र
  • *पिछले समूह को दोहराना है, तो [^/]*इसका मतलब है कि पात्रों को छोड़कर/
  • अब तक sed -n 's;\(http://[^/]*\) अर्थ है खोज और याद रखना, http://इसके बाद किसी भी वर्ण को छोड़कर/ और याद रखें कि आपने क्या पाया है
  • हम डोमेन के अंत की खोज करना चाहते हैं ताकि अगले पर रुकें / ताकि दूसरा जोड़ें/ अंत में :sed -n 's;\(http://[^/]*\)/' लेकिन हम डोमेन के बाद बाकी की रेखा से मेल खाना चाहते हैं.*
  • अब समूह 1 ( \1) में याद किया जाने वाला मैच डोमेन है इसलिए मिलान की गई रेखा को समूह में सहेजे गए सामान से बदल दें\1 और प्रिंट :sed -n 's;\(http://[^/]*\)/.*;\1;p'

यदि आप डोमेन के बाद भी बैकस्लैश शामिल करना चाहते हैं, तो याद रखने के लिए समूह में एक और बैकस्लैश जोड़ें:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'

उत्पादन:

http://www.suon.co.uk/

8
हाल के संपादन के बारे में: कोष्ठक एक प्रकार का ब्रैकेटिंग वर्ण है, इसलिए उन्हें कोष्ठक कहना गलत नहीं है, खासकर यदि आप वास्तविक पात्रों के साथ शब्द का अनुसरण करते हैं, जैसा कि लेखक ने किया था। इसके अलावा, यह कुछ संस्कृतियों में पसंदीदा उपयोग है, इसलिए इसे अपनी संस्कृति में पसंदीदा उपयोग के साथ बदलना थोड़ा अशिष्ट लगता है, हालांकि मुझे यकीन है कि संपादक का इरादा ऐसा नहीं है। निजी तौर पर, मुझे लगता है कि विशुद्ध रूप से वर्णनात्मक नामों का उपयोग करना सबसे अच्छा है जैसे कि गोल कोष्ठक , वर्ग कोष्ठक और कोण कोष्ठक
एलन मूर

2
क्या विभाजक को स्ट्रिंग से बदलना संभव है?
कैल्क्यूलमस

37

sed "गैर लालची" ऑपरेटर का समर्थन नहीं करता है।

आपको "[]" ऑपरेटर को मैच से बाहर करने के लिए "/" का उपयोग करना होगा।

sed 's,\(http://[^/]*\)/.*,\1,'

PS वहाँ "/" बैकस्लैश करने की कोई आवश्यकता नहीं है।


ज़रुरी नहीं। यदि सीमांकक कई संभावित पात्रों में से एक हो सकता है (केवल संख्याओं की एक स्ट्रिंग कहो) तो आपका नकार मैच अधिक से अधिक जटिल हो सकता है। यह ठीक है लेकिन निश्चित रूप से बनाने के लिए एक विकल्प होना अच्छा होगा। * गैर लालची
gesell

1
प्रश्न अधिक सामान्य था। ये समाधान URL के लिए काम करते हैं लेकिन (जैसे) ट्रेलिंग शून्य के मेरे उपयोग के मामले के लिए नहीं। s/([[:digit:]]\.[[1-9]]*)0*/\1/जाहिर है के लिए अच्छा काम नहीं करेगा 1.20300। चूंकि मूल प्रश्न URL के बारे में था, हालांकि, उन्हें स्वीकृत उत्तर में उल्लेख किया जाना चाहिए।
डैनियल एच

33

में आलसी (लालची) की मात्रा का अनुकरण करना sed

और अन्य सभी regex जायके!

  1. अभिव्यक्ति की पहली घटना का पता लगाना:

    • POSIX ERE ( -rविकल्प का उपयोग करके )

      regex:

      (EXPRESSION).*|.

      एसईडी:

      sed -r 's/(EXPRESSION).*|./\1/g' # Global `g` modifier should be on

      उदाहरण (अंकों का पहला अनुक्रम खोजना) लाइव डेमो :

      $ sed -r 's/([0-9]+).*|./\1/g' <<< 'foo 12 bar 34'
      12

      यह कैसे काम करता है ?

      यह रेगेक्स एक प्रत्यावर्तन से लाभान्वित होता है |। प्रत्येक पोजीशन पर इंजन सबसे लंबे मैच को चुनने की कोशिश करता है (यह एक पोसिक्स मानक है, जिसे कुछ अन्य इंजनों के साथ-साथ जोड़ा जाता है) जिसका अर्थ है कि यह .तब तक चलता है जब तक कि कोई मैच नहीं मिल जाता ([0-9]+).*। लेकिन आदेश भी महत्वपूर्ण है।

      यहां छवि विवरण दर्ज करें

      चूंकि वैश्विक ध्वज सेट किया गया है, इंजन इनपुट स्ट्रिंग या हमारे लक्ष्य के अंत तक चरित्र द्वारा मेल खाने वाले चरित्र को जारी रखने की कोशिश करता है। जैसे ही वैकल्पिक के बाईं ओर के पहले और एकमात्र कैप्चरिंग समूह का मिलान किया जाता है(EXPRESSION) बाकी लाइन तुरंत ही खपत हो जाती है .*। अब हम पहले कैप्चरिंग ग्रुप में अपना मान रखते हैं।

    • POSIX BRE

      regex:

      \(\(\(EXPRESSION\).*\)*.\)*

      एसईडी:

      sed 's/\(\(\(EXPRESSION\).*\)*.\)*/\3/'

      उदाहरण (अंकों का पहला क्रम खोजना):

      $ sed 's/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/' <<< 'foo 12 bar 34'
      12

      यह ईआरई संस्करण की तरह है, लेकिन इसमें कोई विकल्प शामिल नहीं है। बस इतना ही। प्रत्येक एकल स्थिति में इंजन एक अंक से मेल खाने की कोशिश करता है।

      यहां छवि विवरण दर्ज करें

      यदि यह पाया जाता है, तो अन्य निम्नलिखित अंकों का सेवन किया जाता है और कब्जा कर लिया जाता है और शेष रेखा को तुरंत मिलान किया जाता है, अन्यथा *इसका मतलब है कि अधिक या शून्य यह दूसरे कैप्चरिंग समूह पर छोड़ देता है \(\([0-9]\{1,\}\).*\)*और डॉट पर आता है. एक एकल वर्ण से मेल करने के लिए और यह प्रक्रिया जारी है।

  2. पहली घटना का पता लगाना सीमांकित अभिव्यक्ति :

    यह दृष्टिकोण एक स्ट्रिंग की पहली घटना से मेल खाता है जो सीमांकित है। हम इसे स्ट्रिंग का एक ब्लॉक कह सकते हैं।

    sed 's/\(END-DELIMITER-EXPRESSION\).*/\1/; \
         s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g'

    इनपुट स्ट्रिंग:

    foobar start block #1 end barfoo start block #2 end

    -EDE: end

    -SDE: start

    $ sed 's/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g'

    आउटपुट:

    start block #1 end

    पहला रेगेक्स \(end\).*मैच करता है और सबसे पहले सीमांकक को पकड़ता है endऔर हाल के कैप्चर किए गए पात्रों के साथ सभी मैच को प्रतिस्थापित करता है जो कि अंतिम सीमांकक है। इस स्तर पर हमारे उत्पादन होता है: foobar start block #1 end

    यहां छवि विवरण दर्ज करें

    फिर परिणाम दूसरे रेगेक्स \(\(start.*\)*.\)*को पास किया जाता है जो ऊपर POSIX BRE संस्करण के समान है। यदि यह सीमांकक startसे मेल नहीं खाता है तो यह एकल वर्ण से मेल खाता है अन्यथा यह प्रारंभ परिसीमन से मेल खाता है और शेष पात्रों से मेल खाता है।

    यहां छवि विवरण दर्ज करें


सीधे अपने सवाल का जवाब

# 2 दृष्टिकोण (सीमांकित अभिव्यक्ति) का उपयोग करते हुए आपको दो उपयुक्त अभिव्यक्तियों का चयन करना चाहिए:

  • EDE: [^:/]\/

  • SDE: http:

उपयोग:

$ sed 's/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'

आउटपुट:

http://www.suepearson.co.uk/

नोट: यह समान सीमांकक के साथ काम नहीं करेगा।


3) डेमो के लिए regex101 जैसी साइटों का सुझाव देते हुए, कृपया ध्यान दें कि यह वाक्यविन्यास और फीचर अंतर के कारण हमेशा cli टूल के लिए उपयुक्त नहीं है
Sundeep

1
@ सुदीप धन्यवाद। मैंने उन सभी कोट्स को सिंगल कोट्स में बदल दिया। इसके अलावा मैंने सबसे लंबे समय तक मैच नियम का उल्लेख किया। हालाँकि sedऔर सभी अन्य इंजन समान मानक आदेश का पालन ​​करते हैं जब यह समानता की बात आती है। तो echo 'foo 1' | sed -r 's/.|([0-9]+).*/\1/g'एक मैच नहीं है, लेकिन echo 'foo 1' | sed -r 's/([0-9]+).*|./\1/g'करता है।
रेवो

भी @Sundeep सीमांकित भाव के लिए वैकल्पिक हल के लिए काम करते नहीं था समान आरंभ और अंत परिसीमक जो मैं के लिए एक नोट जोड़ा।
रेव

जब एक ही स्थान से अलग-अलग विकल्प शुरू होते हैं और एक ही लंबाई होती है, तो इसके बारे में महान बिंदु, अनुमान लगाते हैं कि अन्य इंजनों की तरह बाएं-दाएं क्रम का पालन करेंगे .. अगर मैन्युअल में वर्णित है तो देखने की जरूरत है
Sundeep

हालांकि यहां एक अजीब मामला है: stackoverflow.com/questions/59683820/…
Sundeep

20

एक से अधिक वर्णों के लिए गैर-लालची समाधान

यह धागा वास्तव में पुराना है लेकिन मुझे लगता है कि लोगों को अभी भी इसकी आवश्यकता है। कहते हैं कि आप पहली घटना के बाद तक सब कुछ मारना चाहते हैं HELLO। आप नहीं कह सकते [^HELLO]...

तो एक अच्छा समाधान में दो चरण शामिल हैं, यह मानते हुए कि आप एक अद्वितीय शब्द को छोड़ सकते हैं जिसे आप इनपुट में उम्मीद नहीं कर रहे हैं, कहते हैं top_sekrit

इस मामले में हम कर सकते हैं:

s/HELLO/top_sekrit/     #will only replace the very first occurrence
s/.*top_sekrit//        #kill everything till end of the first HELLO

बेशक, एक सरल इनपुट के साथ आप एक छोटे शब्द, या शायद एक भी चरित्र का उपयोग कर सकते हैं।

HTH!


4
इसे और बेहतर बनाने के लिए, उस स्थिति में उपयोगी है जब आप चरित्र का उपयोग नहीं करने की उम्मीद कर सकते हैं: 1. उस विशेष वर्ण को वास्तव में अप्रयुक्त वर्ड के साथ बदलें, 2. विशेष वर्ण के साथ समाप्त होने वाले अनुक्रम को बदलें, 3. विशेष वर्ण के साथ खोज समाप्त करें, 4 , विशेष वर्ण को वापस बदलें। 5. विशेष शब्द को वापस बदलें। उदाहरण के लिए, आप <hello> और </ hello> के बीच एक लालची ऑपरेटर चाहते हैं:
Jakub

3
यहाँ उदाहरण: प्रतिध्वनि "खोजें: <hello> fir ~ st <br> <br> हाँ </ hello> <hello> sec ~ ond </ hello>" | sed -e "s, ~, VERYSPECIAL, g" -e "s, </ hello>, ~, g" -e "s। * खोजें: <hello> ([^ ~] *)। *, \ 1 , "-ई" s, \ ~, </ hello>, "-e" s, VERYSPECIAL, ~, "
जैकब

2
मैं सहमत हूँ। अच्छा समाधान। मैं टिप्पणी को यह कहकर फिर से बताऊंगा: यदि आप ~ पर अप्रयुक्त होने पर भरोसा नहीं कर सकते हैं, तो इसकी वर्तमान घटनाओं को पहले s / ~ / VERYspeciaL / g का उपयोग करके बदलें, फिर उपरोक्त ट्रिक करें, फिर मूल ~ s / VERspspeciaL / ~ / g का उपयोग करके लौटें।
इशहाक

1
मैं इस तरह की चीज़ों के लिए दुर्लभ "वैरिएबल्स" का उपयोग करना पसंद करता हूं, इसलिए इसके बजाय `, मैं उपयोग करूँगा <$$>(चूंकि $$शेल में आपकी प्रक्रिया आईडी तक फैल जाती है, हालांकि आपको एकल उद्धरणों के बजाय दोहरे उद्धरण चिह्नों का उपयोग करना होगा, और वह आपके regex के अन्य भागों को तोड़ सकता है) या, यदि यूनिकोड उपलब्ध है, तो कुछ ऐसा <∈∋>
एडम काटज़

कुछ बिंदु पर आप अपने आप को पूछने के लिए क्यों तुम सिर्फ उपयोग नहीं कर रहे है perlया pythonबजाय या कुछ अन्य भाषा। perlयह एक ही लाइन में एक कम नाजुक तरीके से करता है ...
ArtOfWarfare

18

sed - गैर लालची क्रिस्टोफ सिघर्ट द्वारा मिलान

गैर लालची सेड में मिलान करने की चाल मैच को समाप्त करने वाले को छोड़कर सभी वर्णों का मिलान करना है। मुझे पता है, एक नो-ब्रेनर, लेकिन मैंने उस पर कीमती मिनट बर्बाद कर दिए और शेल स्क्रिप्ट, सब के बाद, त्वरित और आसान होनी चाहिए। तो मामले में किसी और को इसकी आवश्यकता हो सकती है:

लालची मिलान

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

गैर लालची मिलान

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar

17

यह कटौती का उपयोग करके किया जा सकता है:

echo "http://www.suepearson.co.uk/product/174/71/3816/" | cut -d'/' -f1-3

9

एक और तरीका है, रेगेक्स का उपयोग नहीं करना, उदाहरण के लिए फ़ील्ड / सीमांकक विधि का उपयोग करना है

string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"

5

sed निश्चित रूप से अपनी जगह है, लेकिन यह उनमें से एक नहीं है!

जैसा कि डी ने बताया है: बस उपयोग करें cut। यह इस मामले में कहीं अधिक सरल और अधिक सुरक्षित है। यहाँ एक उदाहरण है जहाँ हम बैश सिंटैक्स का उपयोग करते हुए URL से विभिन्न घटकों को निकालते हैं:

url="http://www.suepearson.co.uk/product/174/71/3816/"

protocol=$(echo "$url" | cut -d':' -f1)
host=$(echo "$url" | cut -d'/' -f3)
urlhost=$(echo "$url" | cut -d'/' -f1-3)
urlpath=$(echo "$url" | cut -d'/' -f4-)

आपको देता है:

protocol = "http"
host = "www.suepearson.co.uk"
urlhost = "http://www.suepearson.co.uk"
urlpath = "product/174/71/3816/"

जैसा कि आप देख सकते हैं कि यह बहुत अधिक लचीला दृष्टिकोण है।

(सभी क्रेडिट डी को)


3
sed 's|(http:\/\/[^\/]+\/).*|\1|'

1
यदि आप "|" आपके विभाजक के रूप में, "/" से बचने की कोई आवश्यकता नहीं है।
माइकल बैक

3

sed -E नियमित अभिव्यक्ति को विस्तारित (आधुनिक) नियमित अभिव्यक्ति के रूप में व्याख्या करता है

अपडेट: -ई पर जीएनयू सेड में मैकओएस एक्स -r पर।


4
नहीं, यह नहीं ... कम से कम GNU sed नहीं।
मिशेल डे Ruiter

7
अधिक मोटे तौर पर, -Eबीएसडी के लिए अद्वितीय है sedऔर इसलिए ओएस एक्स। मैन पेजों के लिए लिंक। -rके रूप में GNUsed में नियमित रूप से विस्तारित अभिव्यक्ति लाता है @ stephancheg के सुधार। निक्स वितरण में ज्ञात परिवर्तनशीलता की एक कमांड का उपयोग करते समय सावधान रहें। मैंने वह कठिन रास्ता सीख लिया।
fny

1
यदि आप sed का उपयोग करना चाहते हैं तो यह सही उत्तर है, और प्रारंभिक प्रश्न पर सबसे अधिक लागू होता है।
विल जाइस

8
जीएनयू सेड का -rविकल्प केवल Appendix A Extended regular expressionsजानकारी फ़ाइल और कुछ त्वरित परीक्षणों के अनुसार, बचने के नियमों को बदलता है ; यह वास्तव में एक गैर-लालची क्वालीफायर ( GNU sed version 4.2.1कम से कम के रूप में ) को
जोड़ता नहीं है

1
GNU सेड को-E थोड़ी देर के लिए एक अनैच्छिक विकल्प के रूप में पहचाना जाता है, लेकिन 4.2.2.177 को रिलीज़ करने में , प्रलेखन को प्रतिबिंबित करने के लिए अद्यतन किया गया है, इसलिए -Eअब दोनों के लिए ठीक है।
बेंजामिन डब्ल्यू

3

शुद्ध (GNU) सेड का उपयोग करके इसे हल करने की उम्मीद अभी भी है। इसके बावजूद कुछ मामलों में यह सामान्य समाधान नहीं है कि आप स्ट्रिंग के सभी अनावश्यक हिस्सों को खत्म करने के लिए "छोरों" का उपयोग कर सकते हैं:

sed -r -e ":loop" -e 's|(http://.+)/.*|\1|' -e "t loop"
  • -r: विस्तारित रेगेक्स का उपयोग करें (के लिए + और unescaped कोष्ठक)
  • "लूप": "लूप" नामक एक नए लेबल को परिभाषित करें
  • -e: sed में कमांड्स जोड़ते हैं
  • "लूप": यदि एक सफल प्रतिस्थापन था, तो "लूप" लेबल पर वापस जाएं

यहां एकमात्र समस्या यह है कि यह अंतिम विभाजक चरित्र ('/') को भी काट देगा, लेकिन अगर आपको वास्तव में इसकी आवश्यकता है तो आप "लूप" समाप्त होने के बाद भी इसे वापस रख सकते हैं, बस पिछले के अंत में इस अतिरिक्त कमांड को जोड़ दें। कमांड लाइन:

-e "s,$,/,"

2

क्योंकि आपने विशेष रूप से कहा था कि आप सीड (पर्ल, कट, आदि के बजाय) का उपयोग करने की कोशिश कर रहे हैं, समूह बनाने की कोशिश करें। यह गैर-लालची पहचानकर्ता को संभावित रूप से मान्यता नहीं देता है। पहला समूह प्रोटोकॉल है (यानी 'http: //', 'https: //', 'tcp: //', आदि)। दूसरा समूह डोमेन है:

इको "http://www.suon.co.uk/product/1/7/3/" | sed "s | ^ \ ((। * // \ _) \ _ ([^ /] * \"। * $ | \ 1 \ 2 "

यदि आप समूहीकरण से परिचित नहीं हैं, तो यहां से शुरू करें


1

मुझे लगता है कि यह एक पुरानी प्रविष्टि है, लेकिन कोई इसे उपयोगी पा सकता है। के रूप में पूर्ण डोमेन नाम 253 वर्णों की कुल लंबाई से अधिक नहीं हो सकता है। *। \ {1, 255 \} के साथ।


1

इस तरह से बहु-वर्ण स्ट्रिंग्स के गैर-लालची मिलान को मजबूती से सेड का उपयोग करना है। यह कहते हैं कि आप इस इनपुट के लिए प्रत्येक foo...barको बदलना चाहते हैं <foo...bar>:

$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV

यह आउटपुट बनना चाहिए:

ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

ऐसा करने के लिए कि आप फू और बार को अलग-अलग वर्णों में परिवर्तित करते हैं और फिर उन वर्णों की उपेक्षा का उपयोग करते हैं:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

ऊपरोक्त में:

  1. s/@/@A/g; s/{/@B/g; s/}/@C/gपरिवर्तित हो रहा है {और }प्लेसहोल्डर स्ट्रिंग्स जो इनपुट में मौजूद नहीं हो सकते हैं, इसलिए उन वर्णों को तब कनवर्ट करने fooऔर उपलब्ध करने के लिए उपलब्ध हैं bar
  2. s/foo/{/g; s/bar/}/gपरिवर्तित fooऔर barकरने के लिए {और }क्रमशः
  3. s/{[^{}]*}/<&>/gहम चाहते हैं कि ऑप प्रदर्शन कर रहा है - करने के foo...barलिए परिवर्तित<foo...bar>
  4. s/}/bar/g; s/{/foo/gपरिवर्तित कर रहा है {और }वापस करने के लिए fooऔरbar
  5. s/@C/}/g; s/@B/{/g; s/@A/@/g प्लेसहोल्डर स्ट्रिंग्स को उनके मूल वर्णों में परिवर्तित कर रहा है।

ध्यान दें कि उपरोक्त किसी विशेष स्ट्रिंग पर निर्भर नहीं करता है जो इनपुट में मौजूद नहीं है क्योंकि यह पहले चरण में इस तरह के तार का निर्माण करता है, और न ही यह ध्यान रखता है कि किसी भी विशेष रेगेक्स की घटना जो आप मेल खाना चाहते हैं क्योंकि आप {[^{}]*}जितनी बार चाहें उपयोग कर सकते हैं अभिव्यक्ति को वास्तविक मैच से अलग करने के लिए जिसे आप चाहते हैं और / या sed सांख्यिक मिलान ऑपरेटर के साथ, उदाहरण के लिए केवल दूसरी घटना को प्रतिस्थापित करें:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV

1

अभी तक इस सवाल का जवाब नहीं देखा है, इसलिए यहाँ आप कैसे साथ ऐसा कर सकते है viया vim:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

यह vi :%sविश्व स्तर पर प्रतिस्थापन (अनुगामी g) को चलाता है , यदि त्रुटि नहीं मिलती है e, तो पैटर्न को नहीं पाया जाता है, ( तब), डिस्क और क्विट के परिणामस्वरूप परिवर्तनों को सहेजता है। &>/dev/nullरोकता है संक्षेप में से जीयूआई स्क्रीन पर चमकती है, जो कष्टप्रद हो सकता है।

मैं viकभी-कभी सुपर कॉम्प्लेक्स रीगेक्स के लिए उपयोग करना पसंद करता हूं , क्योंकि (1) पर्ल डेड मर रहा है, (2) वीआईएम में एक बहुत ही उन्नत रेगेक्स इंजन है, और (3) मैं पहले से ही viअपने दिन-प्रतिदिन उपयोग संपादन में रीगेक्स से परिचित हूं। दस्तावेजों।


0
echo "/home/one/two/three/myfile.txt" | sed 's|\(.*\)/.*|\1|'

परेशान मत करो, मैं इसे एक और मंच पर मिला :)


4
तो आप लालची मैच प्राप्त करते हैं: /home/one/two/three/यदि आप एक और जोड़ते हैं /जैसे /home/one/two/three/four/myfile.txtआप लालची fourरूप में भी मैच करेंगे:, /home/one/two/three/fourसवाल गैर-लालची के बारे में है
stefanB


0

यहाँ कुछ ऐसा है जो आप दो चरणों के दृष्टिकोण और जागरण के साथ कर सकते हैं:

A=http://www.suepearson.co.uk/product/174/71/3816/  
echo $A|awk '  
{  
  var=gensub(///,"||",3,$0) ;  
  sub(/\|\|.*/,"",var);  
  print var  
}'  

आउटपुट: http://www.suepearson.co.uk

उम्मीद है की वो मदद करदे!


0

एक और sed संस्करण:

sed 's|/[:alnum:].*||' file.txt

यह /एक अल्फ़ान्यूमेरिक वर्ण (इसलिए एक और फ़ॉरवर्ड स्लैश) के साथ-साथ पंक्ति के अंत तक बाकी वर्णों से मेल नहीं खाता है । बाद में इसे कुछ नहीं (यानी इसे हटाता है) के साथ बदल देता है।


1
मुझे लगता है कि यह होना चाहिए "[[:alnum:]]", नहीं "[:alphanum:]"
oli_arborum
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.