Quiero sed para reemplazar el patrón coincidente en todo el archivo con valor incremental. Por ejemplo, el patrón de coincidencia es den y quiero que todas las instancias de den en el archivo sean reemplazadas por diez seguidas por una nueva línea y números incrementales. Lo que probé y fallé es:

a=1
while read in; do a=$((a+1)) && sed ""$in"s/den/ten\n"$a"/"; done <<< "$(grep 'den' -o -n file | cut -f1 -d ':')"

Aquí \ n es nueva línea significa que den se reemplaza por diez, luego se agrega nueva línea y en ese nuevo número de línea se agregará. El comando anterior establecerá la variable de bucle $ in con los números de línea en los que aparece la palabra den en el archivo para que sed actúe sobre eso línea e intente reemplazar den con diez \ n $ a. Aquí $ a se incrementará con 1 para cada instancia. Significa que si la primera ocurrencia del den está en la línea 12, luego $ in se establece en 12 y luego sed "12s / den / ten \ n1 /" se ejecutará en bucle y de manera similar cuando la segunda ocurrencia esté en la línea 20 y luego sed "20s / den / ten \ n2 / ".

Salida esperada: por ejemplo, el primer den se reemplazará con diez \ n1, luego el segundo den con diez \ n2 y así sucesivamente.

Pero este comando falla y solo estaba reemplazando la primera generación con $ a = 2 cuando a se establece en 1, pero luego no se reemplazaron otras instancias.

Utilizo números de línea aquí solo porque si solo sed "s / den / den \ n" $ a "/" es usuario, primero todas las ocurrencias de den a la vez y quiero que cada ocurrencia individual sea reemplazada por números incrementales.

Por favor, se necesita ayuda y corrección en el comando. Quiere una solución basada en sed para este problema.

-1
Daichi Ash 26 jun. 2020 a las 12:31

3 respuestas

La mejor respuesta

Usar grep para producir números de línea para sed es decididamente un antipatrón: sed ciertamente puede encontrar las coincidencias de expresiones regulares por sí solo. Pero este problema parece más adecuado para Awk.

awk '{ while(/den/ && sub("den", "ten\n" ++a));; print }' file

Demostración: https://ideone.com/4pGe9l

GNU sed tiene un indicador e que le permite evaluar las expresiones de shell dentro de sed pero no es portátil; De hecho, consideraría que el requisito de resolver esto en sed está mal dirigido en cualquier caso.

2
tripleee 26 jun. 2020 a las 10:19

Use "den" como separador de registros y el número de registro creciente como el incremento:

awk 'BEGIN {RS="den"; ORS=""} NR>1 {printf "ten\n" NR-1} 1' file
1
Walter A 27 jun. 2020 a las 22:37

Siguiente código:

 echo 'For eg first den will be replaced with ten then second den with ten and so on.' |
 # replace "ten" with a "ten" followed a newline and a hash
 sed 's/ten/&\n#/g' |
 # Replace leading hash with a number
 # After each successfull replacement increment number
 awk '{ if (sub(/^#/, i + 1)) i++; } 1'

Salidas:

For eg first den will be replaced with ten
1 then second den with ten
2 and so on.
0
KamilCuk 26 jun. 2020 a las 09:58