
Tenho um problema com meu script a seguir (esta é a 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
Meu objetivo é substituir strings em um arquivo e salvá-lo em um novo. As strings "antigas" e "novas" são armazenadas em um array.
Tentei muitas coisas e brinquei com aspas simples e duplas - mas nada funcionou. Quando utilizo echo
as variáveis, obtenho as strings corretas dentro do loop. Se duas strings explícitas forem definidas no sed
comando, isso funcionará bem.
Os padrões de string seguem aqueles em meus arrays de exemplo ('new' contém o sublinhado "_" e 'old' contém a hashtag "#").
Estou executando o bash em uma caixa Ubuntu 16.04.
Muito obrigado!
Responder1
Crie um sed
script que faça todas as substituições e aplique esse sed
script ao seu arquivo.
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
Dessa forma, você limita o número de vezes que precisa analisar o arquivo de entrada para um.
Para os dados fornecidos OLD
e NEW
o sed
script será gerado como
s/_MAIN1_/#111/g
s/_MAIN2_/#222/g
Responder2
Todo o seu script (que não funciona) pode ser substituído por uma única linha:
sed 's/_MAIN\([12]\)_/#\1\1\1/g' oldfile.txt > newfile.txt
Ou, de forma mais legível, mas equivalente:
sed 's/_MAIN1_/#111/g;s/_MAIN2_/#222/g' oldfile.txt > newfile.txt
Existem várias dezenas de outras maneiras de fazer isso, dependendo do seurealcaso de uso (por exemplo, de onde vêm os dados, como realmente são os valores, o que você está tentando fazer com os dados, etc.).
Responder3
Graças aRakesh Sharmacomentário de eu poderia resolver isso usando o -i
sinalizador no comando sed. Antes do loop, o backup do arquivo original é feito:
cp oldfile.txt oldfile.backup
while (( i < length ))
do
sed -i -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt
((i++))
done
Na próxima vez usarei Perl para manipulações de strings.
Editar:Adicionado ((i++))
para evitar um loop infinito (graças aKusalanandacomentário).