खोज और बदलने के लिए sed और grep / egrep का उपयोग करना


97

मैं egrep -Rलगभग 10 यूनियनों के साथ एक नियमित अभिव्यक्ति का उपयोग कर रहा हूं , जैसे कि: .jpg | .png | .gifआदि। यह अच्छी तरह से काम करता है, अब मैं सभी सभाओं को बदलना चाहता हूं.bmp

मैं जैसे कुछ सोच रहा था

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

तो यहाँ मुद्दा यह है कि मैं एक समान संघ नियमित अभिव्यक्ति sedकैसे करता हूं और मैं इसे फाइल में परिवर्तन को सहेजने के लिए कैसे कहता हूं कि इसे इनपुट मिला।


2
एक निर्देशिका पदानुक्रम में कई फ़ाइलों को खोजने और बदलने के तरीकों की खोज करते हुए मुझे यह प्रश्न मिला। मेरी स्थिति में दूसरों के लिए, आरपीएल का प्रयास करें ।
टाइटेनियमडेकॉय

धन्यवाद rpl काम करता है और वास्तव में याद करने के लिए आसान है .. बस पुराने_string new_string target_files rpl।
cesarpachon

जवाबों:


183

इस कमांड का उपयोग करें:

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep: विस्तारित नियमित अभिव्यक्तियों का उपयोग करके मिलान लाइनें ढूंढें

    • -l: केवल मिलान फ़ाइल नाम की सूची

    • -R: सभी दिए गए निर्देशिकाओं के माध्यम से पुनरावर्ती खोजें

    • -Z: \0रिकॉर्ड विभाजक के रूप में उपयोग करें

    • "\.jpg|\.png|\.gif": तार में से एक से मेल खाते हैं ".jpg", ".gif"या".png"

    • .: वर्तमान निर्देशिका में खोज शुरू करें

  • xargs: तर्क के रूप में स्टड के साथ एक कमांड निष्पादित करें

    • -0: \0रिकॉर्ड विभाजक के रूप में उपयोग करें । यह महत्वपूर्ण मैच के लिए है -Zकी egrepऔर रिक्त स्थान और इनपुट फ़ाइल नामों में नई पंक्तियों से मूर्ख बनाया जा रहा से बचने के लिए।

    • -l: पैरामीटर के रूप में प्रति कमांड एक लाइन का उपयोग करें

  • sed: s tream एड इटोर

    • -i: बैकअप के बिना आउटपुट फ़ाइल को आउटपुट के साथ बदलें

    • -e: अभिव्यक्ति के रूप में निम्न तर्क का उपयोग करें

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': स्ट्रिंग्स की सभी घटनाओं को बदलें ".jpg", ".gif"या ".png"साथ".bmp"


यह छोड़कर सभी काम करता है | sed भाग में। मुझे समझ में नहीं आता कि यद्यपि यह समझ में आता है ... xargs का -l हिस्सा मुझे त्रुटियां दे रहा था इसलिए मैंने इसे निकाल लिया, क्या यह संबंधित हो सकता है?
ओरियल

मैंने पाया कि यह कमांड उन सभी फाइलों के अंत में एक नई पंक्ति जोड़ता है जो इसे संसाधित करता है।
टाइटेनियम

@titanumdecoy: मैं इस व्यवहार को पुन: पेश करने में सक्षम नहीं था। आप किस संस्करण का उपयोग कर रहे थे और आप किस ओएस पर हैं?
डेविड श्मिट

1
@DavidSchmitt: आप शायद sed -rविस्तारित नियमित अभिव्यक्तियों के लिए उपयोग करना चाहते हैं । उस बिंदु पर, पैटर्न का मिलान उसी प्रकार होगा जो एग्रेप में उपयोग किया जाता है, और आप इसे पुन: उपयोग के लिए एक चर में रखना चाह सकते हैं।
17

इस कमांड ने मुझे मेरे द्वारा बनाई गई लाइब्रेरी के लिए हेडर फ़ाइलों को कॉपी करने के काम के घंटे बचाए। यह बहुत ही बढ़िया है :) यहाँ वह कमांड है जिसका मैंने egrep -lRZ "\ .h $" का उपयोग किया था। | xargs -0 tar -cvf हेडर्स.टार | (cp हेडर्स.टार हेडर; सीडी हेडर; टार xf हेडर। टार;)
आलसी कोडर

11

ईमानदारी से, जितना मैं उपयुक्त कार्यों के लिए sed से प्यार करता हूं, यह निश्चित रूप से पर्ल के लिए एक कार्य है - यह इस तरह के वन-लाइनर्स के लिए वास्तव में अधिक शक्तिशाली है, विशेष रूप से "इसे वापस लिखने के लिए जहां यह आता है" (पर्ल के -iस्विच के लिए करता है) आप, और वैकल्पिक रूप से आपको पुराने संस्करण को उदाहरण के लिए एक .bak संलग्न के साथ रखने की सुविधा देता है, बस -i.bakइसके बजाय उपयोग करें )।

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

इसके बजाय sed में जटिल काम (अगर वहां भी संभव है) या awk ...


6
sed उपयोग -i, पर्ल की तरह।
स्टोबोर

@Stobor - मुझे शपथ है कि मेरे पास ऐसे मुद्दे हैं जहां मैंने rexx रिप्लेसमेंट स्ट्रिंग खिलाए जाने पर पर्ल ऑपरेशन किया था, ठीक उसी तरह जो मैं चाहता था, sed के विपरीत, भले ही मैंने regex विकल्प दिया हो sed.. मुझे लगता है कि मैं या तो कुछ झंडे को भूल गया हूँ या इसकी सीमाएँ थीं।
पदक विजेता

10

ऐसा करने का एक और तरीका

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

उपरोक्त कमांड के बारे में कुछ मदद करते हैं

खोज आपके द्वारा दर्शाई गई वर्तमान निर्देशिका पर आपके लिए खोज करेगी .

-name मेरे मामले में फ़ाइल का नाम इसका pom.xml वाइल्ड कार्ड दे सकता है।

-exec निष्पादित

sed धारा संपादक

-i मामले की अनदेखी करें

s स्थानापन्न के लिए है

/4.6.0.../ तलाश की जा रही है

/5.0.0.../ स्ट्रिंग को प्रतिस्थापित किया जाना है


शायद उतना शक्तिशाली नहीं है - लेकिन मेरे लिए स्वीकृत उत्तर की तुलना में यह समझना बहुत आसान है
icc97

5

मेरे लिए काम करने के लिए मुझे इस पृष्ठ पर कोई भी आदेश नहीं मिला: sed समाधान ने सभी संसाधित फ़ाइलों के अंत में एक नई पंक्ति जोड़ी, और पर्ल समाधान खोज से पर्याप्त तर्क स्वीकार करने में असमर्थ था। मुझे यह समाधान मिला जो पूरी तरह से काम करता है:

find . -type f -name '*.[hm]' -print0 
    | xargs -0 perl -pi -e 's/search_regex/replacement_string/g'

यह वर्तमान निर्देशिका वृक्ष नीचे recurse और बदल देगा search_regexके साथ replacement_stringकिसी भी फाइल में में समाप्त होने वाले .hया .m

मैंने पूर्व में भी इस उद्देश्य के लिए rpl का उपयोग किया है।


0

लूप के लिए कुछ प्रयोग करके देखें

 for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done

सुंदर नहीं है, लेकिन करना चाहिए।


3
xargs निश्चित रूप से यहां अधिक उपयुक्त है।
नाथन फेलमैन

1
और |while read iपैटर्न का उपयोग करते हुए स्ट्रीमिंग को सक्षम करने और लंबाई प्रतिबंध से बचने में सक्षम होगा जब egrep के परिणाम बहुत लंबे हो जाते हैं
डेविड श्मिट

0

मेरा उपयोग मामला मैं के foo:/Drive_Letterसाथ प्रतिस्थापित करना चाहता था foo:/bar/baz/xyz मेरे मामले में मैं निम्नलिखित कोड के साथ ऐसा करने में सक्षम था। मैं उसी डायरेक्टरी लोकेशन में था, जहाँ ढेर सारी फाइलें थीं।

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

उम्मीद है कि मदद की।

UPDATE s | foo: / Drive_letter: | foo: / ba / baz / xyz | g


आप सीड कमांड के लिए अन्य सीमांकक का उपयोग कर सकते हैं, और ऐसा करने से मार्ग के नामकरण बहुत अच्छे हो जाते हैं:sed 's|foo:/Drive_letter:|foo:/ba/baz/xyz|g'
केविन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.