script awk para reemplazar múltiples ocurrencias de patrón de cadena en la misma línea en diferentes archivos con un número que coincida con la cadena
Necesito un script awk que busque cualquier cadena dentro de <>, si encuentra una que no ha encontrado antes, debería reemplazarla con el valor actual del contador de índice (0 al principio) e incrementar el contador. Si encuentra una cadena dentro de <> que ya conoce, debería buscar el índice de la cadena y reemplazarla con el índice. Esto debe hacerse en varios archivos, lo que significa que el contador no se restablece cuando se buscan patrones en varios archivos, solo al iniciar el programa. Por ejemplo: 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
debe convertirse
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
Lo que tengo hasta ahora:
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
Pero esto solo puede detectar un patrón <> por línea, pero puede haber múltiples patrones <> por línea. Entonces, ¿cómo debo cambiar el código?
Editar: los archivos no deben editarse, sino que deben crearse nuevos archivos
Respuestas
Usarlo gnu-awk
es más fácil de esta manera usando RS
como <key>
cadena:
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 cualquier 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