¿Cómo puedo agregar un recuento incremental a cada palabra predefinida de un archivo de texto?
Como esta pregunta: ¿Cómo puedo agregar un recuento incremental a cada línea de un archivo de texto?
Quiero agregar un recuento incremental a un archivo de texto. Pero en lugar de agregar un recuento incremental a cada línea, me gustaría agregar un recuento incremental a una palabra predefinida.
Por ejemplo, si quiero contar la palabra "cine" en el texto, me gustaría que todas las apariciones de "cine" se cambien a "cinemaN", donde N es el número incremental y el valor máximo de N depende de cuántas veces aparece la palabra "cine" en el texto.
De modo que un archivo de texto de entrada que contenga este texto:
Condujo su coche al cine. Luego entró al cine para comprar entradas y luego descubrió que habían pasado más de dos años desde la última vez que visitó el cine.
Genera un archivo de salida con este contenido:
Condujo su coche al cine1. Luego entró al cine2 para comprar entradas y luego descubrió que habían pasado más de dos años desde la última vez que visitó el cine3.
Preferiblemente también me gustaría poder numerar la palabra seleccionada en orden inverso.
Es decir, esto generaría un segundo archivo de salida con este contenido:
Condujo su coche al cine3. Luego entró al cine2 para comprar entradas y luego descubrió que habían pasado más de dos años desde la última vez que visitó el cine1.
Respuesta1
Preferiría perl
esto:
$ cat ip.txt
He drove his car to the cinema. He then went inside the cinema to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema.
$ # forward counting is easy
$ perl -pe 's/\bcinema\b/$&.++$i/ge' ip.txt
He drove his car to the cinema1. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema3.
\bcinema\b
palabra a buscar, usando límites de palabras para que no coincida como parte parcial de otra palabra. Por ejemplo,\bpar\b
no coincidiráapart
con opark
ospar
ge
lag
bandera es para reemplazo global.e
permite utilizar código Perl en la sección de reemplazo$&.++$i
es una concatenación de una palabra coincidente y un valor preincrementado cuyo$i
valor predeterminado es0
Para revertir, primero necesitamos obtener el conteo...
$ c=$(grep -ow 'cinema' ip.txt | wc -l) perl -pe 's/\bcinema\b/$&.$ENV{c}--/ge' ip.txt
He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema1.
c
se convierte en una variable de entorno accesible a través del hash%ENV
o, perl
solo, sorbiendo la lima entera
perl -0777 -pe '$c=()=/\bcinema\b/g; s//$&.$c--/ge' ip.txt
Respuesta2
Con GNU awk para RS de varios caracteres, coincidencia que no distingue entre mayúsculas y minúsculas y límites de palabras:
$ awk -v RS='^$' -v ORS= -v word='cinema' '
BEGIN { IGNORECASE=1 }
{ cnt=gsub("\\<"word"\\>","&"); while (sub("\\<"word"\\>","&"cnt--)); print }
' file
He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and afterwards discovered that it was more then two years since he last visited the cinema1.
Respuesta3
Teniendo en cuenta la puntuación después de la palabra.
Numeración directa:
word="cinema"
awk -v word="$word" '
{
for (i = 1; i <= NF; i++)
if ($i ~ word "([,.;:)]|$)") {
gsub(word, word "" ++count,$i)
}
print
}' input-file
Numeración hacia atrás:
word="cinema"
count="$(awk -v word="$word" '
{ count += gsub(word, "") }
END { print count }' input-file)"
awk -v word="$word" -v count="$count" '
{
for (i = 1; i <= NF; i++)
if ($i ~ word "([,.;:)]|$)") {
gsub(word, word "" count--, $i)
}
print
}' input-file
Respuesta4
Para etiquetar la palabra en orden decreciente invertimos la expresión regular E invertimos los datos y finalmente invertimos la fecha una vez más para efectuar la transformación:
perl -l -0777pe '$_ = reverse reverse =~ s/(?=\bamenic\b)/++$a/gre' input.data
Resultado
He drove his car to the cinema3. He then went inside the cinema2 to purchase tickets, and
afterwards discovered that it was more then two years since he last visited the cinema1.
Para etiquetar la palabra en orden creciente, realizamos una búsqueda retrospectiva de la palabra:
perl -lpe 's/\bcinema\b\K/++$a/eg' input.data
Resultado
He drove his car to the cinema1. He then went inside the cinema2 to purchase tickets, and
afterwards discovered that it was more then two years since he last visited the cinema3.