स्ट्रिंग मेल के साथ अलग-अलग फ़ाइलों में एक ही पंक्ति में स्ट्रिंग पैटर्न के कई आवृत्तियों को प्रतिस्थापित करने के लिए awk स्क्रिप्ट

Nov 26 2020

मुझे एक अजीब स्क्रिप्ट की आवश्यकता है जो <> के अंदर किसी भी स्ट्रिंग को खोजती है, अगर यह एक ऐसा है जो इसे पहले नहीं मिला है तो इसे इंडेक्स काउंटर के वर्तमान मूल्य (शुरुआत में 0) से बदलना चाहिए और काउंटर को बढ़ाना चाहिए। यदि इसे <> के अंदर एक स्ट्रिंग मिलती है, जिसे यह पहले से ही जानता है, तो इसे स्ट्रिंग के सूचकांक को देखना चाहिए और इसे सूचकांक के साथ बदलना चाहिए। यह कई फ़ाइलों में किया जाना चाहिए, जिसका अर्थ है कि काउंटर रीसेट नहीं होता है जब कई फाइलें पैटर्न के लिए खोजी जाती हैं, केवल प्रोग्राम स्टार्टअप पर उदाहरण के लिए: file_a.txt:

123abc<abc>xyz
efg
<b>ah
a<c>, <abc>
<c>b
(<abc>, <b>)

file_b.txt:

xyz(<c>, <b>)
xyz<b>xy<abc>z

बन जाना चाहिए

file_a_new.txt:

123abc<0>xyz
efg
<1>ah
a<2>, <0>
<2>b
(<0>, <1>)

file_b_new.txt:

xyz(<2>, <1>)
xyz<1>xy<0>z

मुझे अब तक क्या मिला:

awk 'match($0, /<[^>]+>/) { k = substr($0, RSTART, RLENGTH)
   if (!(k in freq))
      freq[k] = n++
   $0 = substr($0, 1, RSTART-1) freq[k] substr($0, RSTART+RLENGTH) } { print $0 > (FILENAME ".tmp")
}' files

लेकिन यह प्रति पंक्ति केवल एक <> पैटर्न का पता लगा सकता है, लेकिन प्रति पंक्ति एकाधिक <> पैटर्न हो सकता है। तो मुझे कोड कैसे बदलना चाहिए?

संपादित करें: फ़ाइलों को संपादित नहीं किया जाना चाहिए, इसके बजाय नई फाइलें बनाई जानी चाहिए

जवाब

3 anubhava Nov 26 2020 at 17:31

का उपयोग करते हुए gnu-awkइसे इस तरह का उपयोग कर आसान है RSके रूप में <key>स्ट्रिंग:

awk -v RS='<[^>]+>' '{ ORS="" }  # init ORS to ""
RT {                                        # when RT is set
   if (!(RT in freq))                       # if RT is not in freq array
      freq[RT] = n++                        # save n in freq & increment n
   ORS="<" freq[RT] ">"                     # set ORS to < + n + >
}
{
   print $0 > ("/tmp/" FILENAME)
}' file_{a,b}.txt
1 EdMorton Nov 26 2020 at 17:24

किसी भी awk का उपयोग करना:

$ cat tst.awk FNR == 1 { close(out) out = FILENAME ".tmp" } { head = "" tail = $0
    while ( match(tail,/<[^>]+>/) ) {
        tgt = substr(tail,RSTART+1,RLENGTH-2)
        if ( !(tgt in map) ) {
            map[tgt] = cnt++
        }
        head = head substr(tail,1,RSTART) map[tgt]
        tail = substr(tail,RSTART+RLENGTH-1)
    }
    print head tail > out
}

$ head file_*.tmp
==> file_a.txt.tmp <==
123abc<0>xyz
efg
<1>ah
a<2>, <0>
<2>b
(<0>, <1>)

==> file_b.txt.tmp <==
xyz(<2>, <1>)
xyz<1>xy<0>z