
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 echo
las variables, obtengo las cadenas correctas dentro del bucle. Si se establecen dos cadenas explícitas en sed
el 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 sed
script que haga todas las sustituciones y luego aplíquelo sed
a 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 OLD
y NEW
el sed
script 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 -i
bandera 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).