केस-असंवेदनशील खोज और सेड के साथ बदलें


83

मैं एक लॉग फ़ाइल से पाठ निकालने के लिए SED का उपयोग करने का प्रयास कर रहा हूं। मैं बहुत अधिक परेशानी के बिना एक खोज और प्रतिस्थापन कर सकता हूं:

sed 's/foo/bar/' mylog.txt

हालाँकि, मैं खोज के मामले को असंवेदनशील बनाना चाहता हूं। मैंने जो गुगली की है, उससे लगता iहै कि कमांड के अंत में काम करना चाहिए:

sed 's/foo/bar/i' mylog.txt

हालाँकि, यह मुझे एक त्रुटि संदेश देता है:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

यहां क्या गलत हो रहा है, और मैं इसे कैसे ठीक करूं?


2
क्या आप अपने सेड की कॉपी अपडेट करने की कोशिश कर सकते हैं? Iएक GNU एक्सटेंशन है जो आपके sed की कॉपी के साथ उपलब्ध नहीं हो सकता है।
लेज़र

4
संपादित करें : मैं ओएस एक्स योग्यता के माध्यम से मारा, जैसा कि ओपी ने एक जवाब स्वीकार किया है जो ओएस एक्स पर काम नहीं करता है (जैसा कि एक अन्य जवाब में कहा गया है, ओएस एक्स पर सेड केस-असंवेदनशील मिलान का समर्थन नहीं करता है, Apple प्रलेखन के विपरीत।)
danorton 19

1
@danorton: उसके लिए धन्यवाद; यदि आप यह समझ लेते हैं कि Apple प्रलेखन कुछ वादे करता है तो कार्यान्वयन मेरे जवाब से नीचे नहीं होता है: man sedकार्यान्वयन के अनुरूप है - केस-असंवेदनशील मिलान के लिए (और व्यवहार में कोई समर्थन नहीं); अगर आपको अन्यथा दावा करने वाले दस्तावेज का एक टुकड़ा मिला है, तो कृपया हमें बताएं।
mklement0

1
@ mklement0, हां, क्षमा करें, मैं सही हूं। Apple दस्तावेज़ीकरण sed के लिए केस-असंवेदनशील मिलान का कोई दावा नहीं करता है।
danorton

1
FWIW, GNU संस्करणों के उपकरण जिनके BSD संस्करण OS X के साथ आते हैं, विभिन्न पैकेज प्रबंधकों से उपलब्ध हैं। मेरे पास Homebrew के माध्यम से gउपसर्ग के साथ पाठ उपयोगिताओं का पूरा सूट स्थापित है , इसलिए मैं उपयोग कर सकता हूं gsedया gdateजब मुझे स्टॉक संस्करण में नहीं मिल रही सुविधा की आवश्यकता होती है।
मार्क रीड

जवाबों:


73

अपडेट : macOS बिग सुर (11.0) के साथ शुरू , sedअब केस-असंवेदनशील मिलान के लिए ध्वज का समर्थन करता हैI , इसलिए प्रश्न में कमांड को अब काम करना चाहिए (बीएसडी sedइसके संस्करण की रिपोर्ट नहीं करता है, लेकिन आप नीचे तिथि तक जा सकते हैं। का manपेज है, जो होना चाहिए March 27, 2017या अधिक हाल ही में); एक सरल उदाहरण:

# BSD sed on macOS Big Sur and above (and GNU sed, the default on Linux)
$ sed 's/ö/@/I' <<<'FÖO'
F@O   # `I` matched the uppercase Ö correctly against its lowercase counterpart

नोट: I(अपरकेस) ध्वज का प्रलेखित रूप है, लेकिन iसाथ ही साथ काम भी करता है।

इसी तरह, के साथ शुरू MacOS बिग सुर (11.0) awkअब है लोकेल अवगत ( awk --versionरिपोर्ट करना चाहिए 20200816और हाल ही में या):

# BSD awk on macOS Big Sur and above (and GNU awk, the default on Linux)
$ awk 'tolower($0)' <<<'FÖO'
föo  # non-ASCII character Ö was properly lowercased

निम्नलिखित पर लागू होता है MacOS कैटालिना अप करने के लिए (10.15) :

स्पष्ट होने के लिए: macOS पर, sed- जो कि BSD कार्यान्वयन है - केस-असंवेदनशील मिलान का समर्थन नहीं करता है - विश्वास करना मुश्किल है, लेकिन सच है। पूर्व में स्वीकार किए जाते हैं जवाब है, जो अपने आप में एक से पता चलता जीएनयू sed आदेश, की वजह से है कि दर्जा प्राप्त perlआधारित समाधान टिप्पणी में उल्लेख किया है।

यह सुनिश्चित करने के लिए कि पर्ल वर्ण यूटीएफ -8 के माध्यम से विदेशी पात्रों के साथ काम करते हैं , जैसे कुछ का उपयोग करें:

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C धाराओं और फ़ाइलों के लिए UTF-8 समर्थन चालू करता है, मान लें कि वर्तमान स्थान UTF-8-आधारित है।
  • -Mutf8पर्ल को यूटीएफ -8 के रूप में स्रोत कोड की व्याख्या करने के लिए कहता है (इस मामले में, स्ट्रिंग पास हो गई है -pe) - यह अधिक क्रिया के छोटे बराबर है -e 'use utf8;'.धन्यवाद, मार्क रीड

(ध्यान दें कि उपयोग awkकरना एक विकल्प नहीं है , जैसा awkकि macOS (यानी, BWK awk और BSD awk ) पूरी तरह से स्थानों से पूरी तरह से अनभिज्ञ प्रतीत होता है - इसके tolower()और toupper()फ़ंक्शंस विदेशी वर्णों को अनदेखा करते हैं (और sub()/ gsub()शुरू करने के लिए केस-इंसेंसिटिव फ़्लैग नहीं होते हैं) साथ में)।)


sedऔर awkPOSIX मानक के संबंध पर एक नोट :

BSD sedऔर awkअपनी कार्यक्षमता को ज्यादातर POSIXsed और POSIX के लिएawk जनादेश को सीमित करता है , जबकि उनके GNU समकक्ष कई और एक्सटेंशन लागू करते हैं।


स्थान तय करने के लिए: blogs.agilefaqs.com/2014/01/12/…
Eduardo Cuomo

69

संपादक का ध्यान दें : यह समाधान macOS (बॉक्स से बाहर) पर काम नहीं करता है, क्योंकि यह केवल GNU पर लागू होता है sed, जबकि macOS BSD से आता है sed

'I' को कैपिटलाइज़ करें।

sed 's/foo/bar/I' file

2
मैंने यह भी देखा, और यह कोशिश की ... लेकिन मुझे अभी भी वही त्रुटि संदेश मिलता है।
क्रेग वॉकर

15
BSD sed में बहुत सी सीमाएँ हैं, ऐसा लगता है। यदि यह मामला है, तो मैं इसे पर्ल (यानी, पर्ल-एसपी / फू / बार / आई ') में करूंगा।
वेस्ले राइस

3
OS X Lion की डिफ़ॉल्ट स्थापना त्रुटि देती है: sed: 1: "s / foo / bar / I": विकल्प कमांड में खराब ध्वज: 'I'
बेन क्लेटन

13
Iप्रत्यय के एक पोर्टेबल उपयोग नहीं है sed। POSIX sedकेवल बेसिक रेगुलर एक्सप्रेशन (BREs) का उपयोग करता है , जो आश्चर्यजनक रूप से सीमित हैं। वे भी समर्थन नहीं करते +(आपको \{1,\}इसके बजाय उपयोग करना होगा), अकेले मामले को असंवेदनशील मिलान होने दें। सेड के साथ ऐसा करने का एकमात्र पोर्टेबल तरीका कुछ ऐसी चीज़ों की जांच करना है /[hH][eE][lL][lL][oO]/, जो अक्सर अव्यवहारिक होने वाली है।
इडम

5
यह /gIकेवल पहले मैच पर संचालित होगा एक दूसरे के लिए आवश्यक है।
फहीम मीठा

25

sedमैक ओएस एक्स के लिए एक और काम के आसपास gsedMacPorts या HomeBrew से इंस्टॉल करना है और फिर उपनाम बनाना है sed='gsed'


"s / a / b / Ig" काम करता है, धन्यवाद! एक अच्छा काम करने वाले उत्तर को एक गिरावट क्यों मिलनी चाहिए?
मथायस एम

3
यह जवाब बहुत अच्छा है। इस्तेमाल किया brew install gnu-sedतो मेरे ~ / .bash_profile पर गया और उपनाम जोड़ा। साभार @davmat
ThinkBonobo

8
बेहतर करने के लिए brew install gnu-sed --with-default-names- यह डिफ़ॉल्ट को ओवरराइड करेगा sed
Mar0ux

5

Sed पूछे जाने वाले प्रश्न पतों बारीकी से संबंधित केस-संवेदी खोज । यह इंगित करता है कि ए) सेड के कई संस्करण इसके लिए एक ध्वज का समर्थन करते हैं और बी) यह sed में करने के लिए अजीब है, आपको बल्कि awk या पर्ल का उपयोग करना चाहिए।

लेकिन इसे POSIX sed में करने के लिए , वे तीन विकल्प सुझाते हैं (यहाँ प्रतिस्थापन के लिए अनुकूलित):

  1. होल्ड स्पेस में अपरकेस और मूल लाइन को स्टोर करना; यह प्रतिस्थापन के लिए काम नहीं करेगा, हालांकि, मूल सामग्री को मुद्रण से पहले बहाल किया जाएगा, इसलिए यह केवल केस-असंवेदनशील मैच के आधार पर लाइनों को सम्मिलित करने या जोड़ने के लिए अच्छा है।

  2. शायद संभावनाएँ सीमित हैं FOO, Fooऔर foo। इनके द्वारा कवर किया जा सकता है

     s/FOO/bar/;s/[Ff]oo/bar/
    
  3. सभी संभावित मैचों की खोज करने के लिए, प्रत्येक वर्ण के लिए कोष्ठक के भावों का उपयोग किया जा सकता है:

     s/[Ff][Oo][Oo]/bar/
    

pubs.opengroup.org/onlinepubs/9699919799/utilities/rew.html वह है जो आप आसानी से sed में कर सकते हैं
D.Shawley

@ D.Shawley यह जवाब में कुछ भी विरोधाभास नहीं है, है ना? या आप आधिकारिक कल्पना से जोड़कर संदर्भ जोड़ना चाहते थे? मैं इसे उत्तर में जोड़ सकता हूं।
बेंजामिन डब्ल्यू।

डब्ल्यू यहां कुछ भी विरोधाभासी नहीं है। मैं किसी को POSIX का संदर्भ देते हुए देखकर खुश था और एक लिंक जोड़ना चाहता था। यहाँ बहुसंख्यक उत्तर "गैर-मानक" मैक के कार्यान्वयन के लिए व्यस्त थे जो मुझे परेशान करते थे।
डी। शेले

@ D.Shawley ने अब कल्पना की एक कड़ी जोड़ दी :)
बेंजामिन डब्ल्यू।

3

यदि आप पैटर्न मिलान पहले कर रहे हैं, जैसे,

/pattern/s/xx/yy/g

तो आप Iपैटर्न के बाद रखना चाहते हैं :

/pattern/Is/xx/yy/g

उदाहरण:

echo Fred | sed '/fred/Is//willma/g'

रिटर्न willma; इसके बिना I, यह स्ट्रिंग को अछूता ( Fred) लौटाता है ।


2
मैकओ पर मुझे मिलता है:sed: 1: "/fred/Is//willma/g": invalid command code I
क्रिस एफ कैरोल

अच्छा सुझाव। यहां बताया गया है कि मैं इसे एक जटिल खोज पर कैसे उपयोग करता हूं sed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3':। यह पाठ को प्रिंट करता है, और यदि पैटर्न (केस-असंवेदनशील) पाया गया, तो यह पाठ को पीले (एएनआई रंग) में हाइलाइट करता है। अगर नहीं मिला - रिटर्न एग्जिट कोड 3.
नोम मानोस

1

मैक संस्करण sedथोड़ा सीमित लगता है। इसके चारों ओर काम करने का एक तरीका यह है कि एक लिनक्स कंटेनर (डॉकर के माध्यम से) का उपयोग किया जाए, जिसका उपयोग करने योग्य संस्करण है sed:

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'

17
यह करने के लिए एक विशेष रूप से जघन्य बात है। यदि कोई भी इस पर गंभीरता से विचार कर रहा है, तो बस स्थानीय रूप से एक GNU सेड स्थापित करें।
ऑसोडो

पता करने के लिए ओवरकिल लेकिन उपयोगी सामान्य दृष्टिकोण!
यवसगेरे

0

मुझे इसी तरह की आवश्यकता थी, और इसके साथ आया:

यह कमांड बस सभी फाइलों को खोजने के लिए है:

grep -i -l -r foo ./* 

इसे इस_shell.sh को बाहर करने के लिए (यदि आपने इस स्क्रिप्ट में कमांड को इस_शेल.श ) के नाम से रखा है , तो कंसोल पर आउटपुट को देखें कि क्या हुआ, और फिर पाठ फ़ाइल को बार से बदलने के लिए मिली प्रत्येक फ़ाइल नाम पर sed का उपयोग करें :

grep -i -l -r --exclude "this_shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

मैंने इस विधि को चुना, क्योंकि मुझे नहीं संशोधित फ़ाइलों के लिए सभी टाइमस्टैम्प को बदलना पसंद था। जीआरपी परिणाम खिलाने से केवल लक्ष्य पाठ वाली फाइलों को देखा जा सकता है (इस प्रकार प्रदर्शन / गति में भी सुधार हो सकता है)

उपयोग करने से पहले अपनी फ़ाइलों और परीक्षण का बैकअप लेना सुनिश्चित करें। एम्बेडेड स्पेस वाली फ़ाइलों के लिए कुछ वातावरण में काम नहीं कर सकते। (?)


0

सभी घटनाओं को बदलने के लिए निम्नलिखित का उपयोग करें: sed 's / foo / bar / gI' mylog.txt


Stackoverflow.com/a/4412964/4294399 देखें , जो राजधानी को कवर करता है I। मुझे नहीं लगता कि यह वास्तव में इस सवाल का जवाब देता है क्योंकि यह वैश्विक प्रतिस्थापन के बारे में नहीं पूछता है।
Calculuswhiz
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.