script awk para substituir várias ocorrências de padrão de string na mesma linha em arquivos diferentes com número correspondente à string
Eu preciso de um script awk que procure qualquer string dentro de <>, se encontrar alguma que não tenha encontrado antes, deve substituí-la pelo valor atual do contador de índice (0 no início) e incrementar o contador. Se encontrar uma string dentro de <> que já conhece, ele deve procurar o índice da string e substituí-lo pelo índice. Isso deve ser feito em vários arquivos, o que significa que o contador não zera quando vários arquivos são pesquisados em busca de padrões, apenas na inicialização do programa. Por exemplo: 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
Deve se tornar
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
O que consegui até agora:
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
Mas isso só pode detectar um <> padrão por linha, mas pode haver vários <> padrões por linha. Então, como devo alterar o código?
Editar: Os arquivos não devem ser editados, em vez disso, novos arquivos devem ser criados
Respostas
Usá- gnu-awk
lo é mais fácil desta forma usando RS
como <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
Usando qualquer 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