सही लाइन खोजने के लिए Grep, सामग्री बदलने के लिए sed, फिर इसे मूल फ़ाइल में वापस लाना?


9

मैं एक फ़ाइल में एक विशिष्ट लाइन पर एक शब्द को बदलने की कोशिश कर रहा हूं, लेकिन मुझे सभी को एक साथ जोड़ने में थोड़ी परेशानी हो रही है।

असल में, मेरी फाइल में एक लाइन पर एक कीवर्ड 'फर्मवेयर_रीविजन' है, और इस लाइन पर (और केवल यही लाइन) मैं 'टेस्ट' शब्द को 'प्रोडक्शन' शब्द से बदलना चाहता हूं।

तो मैं यह कर सकता हूँ:

grep 'firmware_revision' myfile.py | sed 's/test/production'

यह वह लाइन चुन लेगा जिसे मैं चाहता हूं और प्रतिस्थापन का प्रदर्शन करता हूं, लेकिन मैं यह पता नहीं लगा सकता कि पुरानी लाइन को बदलने के लिए इस नई लाइन को मूल फ़ाइल में कैसे लाया जाए। मैं स्पष्ट रूप से इसे केवल फ़ाइल पर वापस नहीं भेज सकता, इसलिए मुझे क्या करना चाहिए?

यहां तक ​​कि अगर मैं अस्थायी grepलाइन का उपयोग करता हूं, तो मुझे केवल उस लाइन को प्राप्त करने के लिए उपयोग करने की आवश्यकता है जो मुझे फ़ाइल में अन्य डेटा खो देता है, इसलिए मैं अब इसे केवल एक अस्थायी फ़ाइल पर पुनर्निर्देशित नहीं कर सकता हूं, फिर मूल को अस्थायी के साथ बदल दें।

संपादित करें - किसी ने अधिक जानकारी मांगी

कहते हैं, मेरे पास इस तरह की लाइनों से भरी एक फाइल है

[
  ('key_name1', str, 'value1', 'Description'),
  ('key_name2', str, 'value2', 'Description'),
  ('key_name3', str, 'value3', 'Description'),
  ('firmware_revision', str, 'my-firmware-name-test', 'Firmware revision name')
]

अब मैं एक स्क्रिप्ट लिखना चाहता हूं (आदर्श रूप से एक-लाइनर) जिसमें वह लाइन मिल जाएगी जिसमें 'फर्मवेयर_रीविजन' है, और उस लाइन पर 'टेस्ट' शब्द के सभी उदाहरणों को 'प्रोडक्शन' में बदल देता है। 'परीक्षण' शब्द उस फ़ाइल में अन्य स्थानों पर हो सकता है और मैं नहीं चाहता कि वे बदले। तो स्पष्ट होने के लिए, मैं उपरोक्त लाइन को बदलना चाहता हूं

('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')

मैं यह कैसे करु?


5
sedबहुत शक्तिशाली है, यह दोनों कार्यों ( grepऔर प्रतिस्थापन) का प्रदर्शन कर सकता है लेकिन हमें इस बारे में अधिक जानकारी की आवश्यकता होगी कि रेखा आपकी मदद कैसे करती है।
grochmal

मैं मूल पोस्ट में अधिक जानकारी
जोड़ूंगा

7
कोशिश करें:sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
जॉन 1024

1
आह यह पूरी तरह से काम किया! क्या आप वाक्य रचना की व्याख्या कर सकते हैं?
जॉन एलार्ड

@ जॉनऑलार्ड बहुत अच्छा। मैंने स्पष्टीकरण के साथ एक उत्तर जोड़ा।
जॉन 1024

जवाबों:


22

प्रयत्न:

sed -i.bak '/firmware_revision/ s/test/production/' myfile.py

यहाँ, /firmware_revision/एक शर्त के रूप में कार्य करता है। यह उन पंक्तियों के लिए सही है जो रेगेक्स से मेल खाती हैं firmware_revisionऔर अन्य लाइनों के लिए झूठी हैं। यदि स्थिति सही है, तो जो आदेश निम्नानुसार निष्पादित किया गया है। इस मामले में, कि आदेश एक विकल्प के आदेश की पहली आवृत्ति को बदल देता है testके साथ production

दूसरे शब्दों में, कमांड s/test/production/को केवल उन पंक्तियों पर निष्पादित किया जाता है जो रेगेक्स से मेल खाते हैं firmware_revision। अन्य सभी लाइनें अपरिवर्तित से गुजरती हैं।

डिफ़ॉल्ट रूप से, sed अपने आउटपुट को मानक से बाहर भेजता है। हालाँकि, आप फ़ाइल को जगह में बदलना चाहते थे। इसलिए, हमने -iविकल्प जोड़ा । विशेष रूप से, -i.bakफ़ाइल को .bakएक्सटेंशन के साथ सहेजे गए बैक-अप कॉपी के साथ बदल दिया जाता है ।

यदि आपने तय किया है कि कमांड आपके लिए काम करता है और आप खतरनाक तरीके से जीना चाहते हैं और बैकअप नहीं बनाते हैं, तो, GNU sed (लिनक्स) के साथ, का उपयोग करें:

sed -i '/firmware_revision/ s/test/production/' myfile.py

इसके विपरीत, BSD (OSX) पर, -iविकल्प में एक तर्क होना चाहिए। यदि आप बैकअप नहीं रखना चाहते हैं, तो उसे खाली तर्क प्रदान करें। इस प्रकार, उपयोग करें:

sed -i '' '/firmware_revision/ s/test/production/' myfile.py

संपादित करें

प्रश्न को संपादित करने के लिए, ओपी को लाइन पर होने वाली हर घटना को testबदलने के लिए कहता है production। उस स्थिति में, हम gविकल्प को वैश्विक (उस लाइन के लिए) प्रतिस्थापन के लिए विकल्प जोड़ते हैं :

sed -i.bak '/firmware_revision/ s/test/production/g' myfile.py

5
पूर्णता के लिए, आप इस -i.bakभाग को भी समझाना चाह सकते हैं ।
स्टीफन हैरिस

5
@StephenHarris अच्छी बात है। -iजोड़ा का स्पष्टीकरण ।
जॉन १०२४

मुझे लगता है कि आप शायद सितारों तक पहुंच सकते हैं, बस किताब पर खड़े होकर सभी चीजें बता sedसकते हैं ...
KlaymenDK

@ John1024 नहीं बीएसडी लोगों के लिए, आप पहली बार के कारणों के जोड़ सकता है ''के बाद -i?
हस्तूर

3
ओपी उस लाइन पर 'टेस्ट' शब्द के सभी उदाहरणों को 'प्रोडक्शन' में बदलना चाहते थे । इस मामले में सेड कमांड को जोड़ना / छोडना महत्वपूर्ण है: sed -i '/firmware_revision/ s/test/production/g' myfile.pyअन्यथा केवल पहला उदाहरण बदल जाता है।
knub

4

पुराने स्कूलों के साथ पुरानी मशीनों पर sedजो विकल्प का समर्थन नहीं करता है -i:

TF=$( mktemp -t "${0##*/}"_$$_XXXXXXXX ) && \
trap 'rm -f "$TF"' EXIT HUP INT QUIT TERM && \
sed '/firmware_revision/ s/test/production/' myfile.py >"$TF" && \
mv -f "$TF" myfile.py

1
उन पुरानी मशीनों पर जिन्हें आप बस edएक लाइन में इस्तेमाल और कर सकते हैं :printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
don_crissti

1
@don_crissti बहुत सही है, लेकिन ed(1)इसका उपयोग दिखाने के लिए कोई बहाना नहीं देता है mktemp(1)
सातु कटुरा

यदि आप एक टेंपरेचर का उपयोग कर रहे हैं, तो आप मूल फ़ाइल के इनोड और पर्म को भी रख सकते हैं, जैसा कि edकरता है। इसके बजाय mv -f "$TF" myfile.pl, उपयोग करें cat "$TF" > myfile.pl && rm -f "$TF"। BTW, लोअरकेस वैरिएबल नामों ( $tfइसके बजाय $TF) का उपयोग करना अच्छा है , वे किसी भी बैश बिल्ट-इन वैर (शायद अन्य बॉर्न शेल भी) के साथ संघर्ष नहीं करने की गारंटी देते हैं।
कैस

पुन:: cat "$TF" > myfile.plयह प्रयास करें: touch a b; chmod 0444 a; cat b >a(BTW, sed -iउस मामले में भी काम नहीं करेगा)। बेहतर है कि उपयोगकर्ता को इससे निपटने दें। पुन: rm -f "$TF"जरूरत नहीं है, देखें trap ... EXIT। पुन: $tfइसके बजाय $TF: हो सकता है; यह स्टाइल की बात है।
सातु कटसरा

यह सामान्य है और यूनिक्स फ़ाइल अनुमतियों का अपेक्षित व्यवहार है। मेरा कहना यह था कि एक नई फ़ाइल बनाना और मूल-इच्छा से अधिक एमवी-आईएनजी 1. उस फ़ाइल नाम के लिए एक नया इनकोड (किसी भी हार्ड-लिंक को तोड़ना) के परिणामस्वरूप। 2. यदि संभव हो तो परमिट बदल दें, यदि वर्तमान umask मूल परमिट से अलग है। अपरकेस वैर के रूप में, यह सिर्फ स्टाइल की बात नहीं है - बहुत से ऐसे लोग हैं जिन्होंने अपरकेस पैथ या रैंडम या शेल या जो कुछ भी अपने स्वयं के चर के लिए उपयोग करने की गलती की है, ने कठिन रास्ता खोज लिया है। (और हाँ, मैं अक्सर अपने आप को अपरकेस वेरिएस का उपयोग करता हूं। मुझे पता है कि यह गलत है, मैं आदत को तोड़ने की कोशिश कर रहा हूं)।
कैस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.