Bash mientras busca en bucle y reemplaza usando sed

Bash mientras busca en bucle y reemplaza usando sed

Tengo un problema con mi siguiente script (esta es la parte relevante):

#!/bin/bash

OLD=(
"_MAIN1_"
"_MAIN2_"
)

NEW=(
"#111"
"#222"
)

length=${#OLD[*]}

i=0

while (( i < length ))
do
  sed -e "s/${OLD[$i]}/${NEW[$i]}/g" oldfile.txt > newfile.txt

  #sed -e 's/_MAIN1_/#111/g' oldfile.txt > newfile.txt  # this works

  # Another way that does not work
  #sed -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt > newfile.txt

  ((i++))
done

exit 0

Mi objetivo es reemplazar cadenas en un archivo y guardarlo en uno nuevo. Las cadenas "antiguas" y "nuevas" se almacenan en una matriz.

Probé muchas cosas y jugué con comillas simples y dobles, pero nada funcionó. Cuando analizo echolas variables, obtengo las cadenas correctas dentro del bucle. Si se establecen dos cadenas explícitas en sedel comando, funciona bien para esto.

Los patrones de cadena siguen los de mis matrices de ejemplo ('nuevo' contiene el guión bajo "_" y 'antiguo' contiene el hashtag "#").

Estoy ejecutando bash en una caja Ubuntu 16.04.

¡Muchas gracias!

Respuesta1

Cree un sedscript que haga todas las sustituciones y luego aplíquelo seda su archivo.

for (( i=0; i<${#OLD[@]}; ++i )); do
        printf 's/%s/%s/g\n' "${OLD[$i]}" "${NEW[$i]}"
done >script.sed

sed -f script.sed inputfile >outputfile && mv outptufile inputfile && rm script.sed

De esta manera, limita la cantidad de veces que necesita analizar el archivo de entrada a una.

Para los datos proporcionados en OLDy NEWel sedscript se generará como

s/_MAIN1_/#111/g
s/_MAIN2_/#222/g

Respuesta2

Todo el script (que no funciona) se puede reemplazar con una sola línea:

sed 's/_MAIN\([12]\)_/#\1\1\1/g' oldfile.txt > newfile.txt

O, de manera más legible pero equivalente:

sed 's/_MAIN1_/#111/g;s/_MAIN2_/#222/g' oldfile.txt > newfile.txt

Hay varias docenas de otras formas de lograr esto, dependiendo de suactualcaso de uso (por ejemplo, de dónde provienen los datos, cómo se ven realmente los valores, qué está tratando de hacer con los datos, etc.).

Respuesta3

Gracias aRakesh SharmaComentario: Podría resolver esto usando la -ibandera en el comando sed. Antes del bucle, se realiza una copia de seguridad del archivo original:

cp oldfile.txt oldfile.backup
while (( i < length ))
do
  sed -i -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt
  ((i++))
done

La próxima vez usaré Perl para manipular cadenas.

Editar:Agregado ((i++))para evitar un bucle infinito (Gracias aKusalanandacomentario de).

información relacionada