मैं एक फाइल में लाइनों को बदलने के लिए देख रहा हूँ। यानी अगर "ओल्डटेक्स्ट" एक लाइन की शुरुआत में फाइल में है, तो पूरी लाइन को "newtext" से बदलें।

लाइन का प्रारंभ ^oldtext या oldtext हो सकता है, कुछ व्हाइटस्पेस/टैब द्वारा इंडेंट किया जाएगा

grep "^[\S]oldtext" myfile.txt   # doesn't work

मुझे उसी इंडेंटेशन स्तर की गणना करने की आवश्यकता है जो "ओल्डटेक्स्ट" था

prefixspaces = <number of spaces before the "mytext", converting tabs to 4 spaces>

मुझे एहसास है कि sed शायद इसे हासिल करने का सबसे अच्छा तरीका है, लेकिन मुझे किसी तरह पहले उपसर्ग स्थान की गणना करने की आवश्यकता है, फिर मेरा आउटपुट कुछ ऐसा है:

sed -i -e 's/^$prefixspaces$newtext*$/$prefixspaces$newtext/g' myfile.txt

इसकी गणना कैसे करें, यह काम नहीं कर सकता। हो सकता है कि $prefixspace को एक समूह () या कुछ और में रखा जा सकता है ताकि sed आसानी से गणना कर सके और उसके साथ काम कर सके? शायद यह एक sed या awk वन-लाइनर है, लेकिन मैं कुछ खोज के बाद इसे काम नहीं कर सकता।

2
YorSubs 15 नवम्बर 2020, 11:08

3 जवाब

सबसे बढ़िया उत्तर

इस कदर:

sed 's/^\( *\)oldtext.*/\1newtext/' file

व्याख्या:

खोज

^             beginning of the line
\( *\)        capture 0 or more spaces in group 1
oldtext       'oldtext'
.*            rest of the line

बदलें

\1            the 0 or more spaces from group1
newtext       'newtext'
3
hek2mgl 15 नवम्बर 2020, 13:35

यह आपके लिए काम कर सकता है (GNU sed):

sed '/^\s*oldtext/s/\S.*/newtext/' file

oldtext को एक लाइन या इंडेंट की शुरुआत में मैच करें और पहले नॉन-व्हाइट स्पेस कैरेक्टर से बदलें।

1
potong 15 नवम्बर 2020, 17:33

sed के साथ

ऐसा करने का एक और तरीका, स्वीकृत उत्तर के अतिरिक्त, वर्ग वर्णों ([[:space:]]) का उपयोग कर रहा है, और -r पैरामीटर के साथ नियमित अभिव्यक्तियों का विस्तार कर रहा है:

$ sed -r 's/^([[:space:]]*)oldtext.*/\1newtext/' << _eof
  oldtext this
 a
    oldtext also this
_eof

और परिणाम होगा:

  newtext
 a
    newtext

([[:space:]]*) में, हमने शून्य या अधिक रिक्त स्थान वाले समूह पर कब्जा कर लिया, लेकिन हम एक निश्चित संख्या निर्दिष्ट कर सकते हैं।

awk के साथ

हम रिक्त स्थान को बदलने और समय गिनने के लिए gsub का उपयोग कर सकते हैं:

$ awk \
    -v old="oldtext" \
    -v new="newtext" \
    'BEGIN{re="^[[:space:]]*"old}
{
  if (match($0,re)) {
    i=gsub(/ /,"")
    while (--i) printf " "
    print new
  }
  else 
    print
}' << _eof
  oldtext this
oldtext also this
    oldtext and this
  oldtext also this
_eof

और परिणाम होगा:

  newtext
 newtext
     newtext
   newtext

perl के साथ

हम इसे perl के उपयोग से sed-like शैली में प्राप्त कर सकते हैं:

$ perl -lpe 's/^(\s*)oldtext.*/\1newtext/' << _eof
  oldtext this
oldtext this
    oldtext this
  oldtext also this
_eof

और परिणाम होगा:

  newtext
newtext
    newtext
  newtext
1
Cuauhtli 15 नवम्बर 2020, 22:02