
У меня возникла проблема с моим следующим скриптом (это его соответствующая часть):
#!/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
Моя цель — заменить строки в файле и сохранить его в новый. «Старые» и «новые» строки хранятся в массиве.
Я пробовал много вещей и игрался с одинарными и двойными кавычками - но ничего не работало. Когда я echo
переменные, я получаю правильные строки внутри цикла. Если явно две строки заданы в sed
команде, это работает нормально.
Шаблоны строк соответствуют шаблонам в моих примерах массивов («new» содержит подчеркивание «_», а «old» содержит хэштег «#»).
Я запускаю bash на компьютере с Ubuntu 16.04.
Большое спасибо!
решение1
Создайте sed
скрипт, который выполнит все замены, а затем примените этот sed
скрипт к своему файлу.
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
Таким образом, вы ограничиваете количество раз, которое вам необходимо будет анализировать входной файл, одним.
Для заданных данных в OLD
и NEW
скрипт sed
будет сгенерирован как
s/_MAIN1_/#111/g
s/_MAIN2_/#222/g
решение2
Весь ваш скрипт (который не работает) можно заменить одной строкой:
sed 's/_MAIN\([12]\)_/#\1\1\1/g' oldfile.txt > newfile.txt
Или, более читабельно, но эквивалентно:
sed 's/_MAIN1_/#111/g;s/_MAIN2_/#222/g' oldfile.txt > newfile.txt
Есть несколько десятков других способов сделать это, в зависимости от вашегодействительныйвариант использования (например, откуда берутся данные, как на самом деле выглядят значения, что вы пытаетесь сделать с данными и т. д.).
решение3
БлагодаряРакеш Шармакомментарий Я мог бы решить эту проблему, используя -i
флаг в команде sed. Перед циклом исходный файл резервируется:
cp oldfile.txt oldfile.backup
while (( i < length ))
do
sed -i -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt
((i++))
done
В следующий раз я буду использовать Perl для работы со строками.
Редактировать:Добавлено ((i++))
для предотвращения бесконечного цикла (СпасибоКусаланандакомментарий).