skrypt awk do zamiany wielu wystąpień wzorca łańcuchowego w tej samej linii w różnych plikach na liczbę pasującą do łańcucha
Potrzebuję skryptu awk, który wyszukuje dowolny ciąg wewnątrz <>, jeśli znajdzie taki, którego nie znalazł przedtem, powinien zastąpić go bieżącą wartością licznika indeksu (0 na początku) i zwiększyć licznik. Jeśli znajdzie łańcuch wewnątrz <>, który już zna, powinien sprawdzić indeks tego ciągu i zastąpić go indeksem. Należy to zrobić dla wielu plików, co oznacza, że licznik nie resetuje się, gdy wiele plików jest przeszukiwanych w poszukiwaniu wzorców, tylko podczas uruchamiania programu Na przykład: plik_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
powinno stać się
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
Co mam do tej pory:
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
Ale to może wykryć tylko jeden wzorzec <> na linię, ale może istnieć wiele wzorców <> w linii. Jak więc mam zmienić kod?
Edycja: Pliki nie powinny być edytowane, zamiast tego powinny zostać utworzone nowe pliki
Odpowiedzi
Używanie gnu-awk
go jest łatwiejsze w ten sposób, używając RS
jako <key>
string:
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
Używanie dowolnego 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