Intereting Posts
Bash: для цикла с двоичным диапазоном, сохраняющим контрольное значение двоичным Как создать массив уникальных элементов из строки / массива в bash? Segfault на сервере debian Как избежать cp -r ~ / some / folder /. копирование всех файлов на верхний уровень текущей папки? Как установить meld 3.11 в Ubuntu 14.04? Найти каталог и скопировать другой каталог в найденный каталог? Как записать изображение iso из командной строки выяснить, какие файловые дескрипторы используют одно и то же «описание открытого файла», Убить процесс, когда он перестает производить дальнейший вывод Список всех ключей, подписанных данным ключом Как получить IP-адрес устройства, открытый в сети простым способом? в чем разница между `>> / dev / stderr` (с пробелом) и`> & 2`? Как установить cpupower на Ubuntu 14.04 (ядро 4.6.0) Как печатать ip с iftop, отсортированным по использованию полосы пропускания «convert» занимает много времени, чтобы создать миниатюру PNG

Bash при поиске цикла и замене с помощью sed

У меня проблема с моим следующим скриптом (это его часть):

#!/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» содержит символ подчеркивания «_» и «старый», содержащий хэштегов «#»).

Я запускаю bash на ящике Ubuntu 16.04.

Большое спасибо!

Создайте сценарий 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 

Весь ваш скрипт (который не работает) можно заменить одной строкой:

 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 

Существует несколько десятков других способов достижения этого, в зависимости от вашего фактического использования (например, откуда поступают данные, какие значения действительно выглядят, что вы пытаетесь сделать с данными и т. Д.).

Благодаря комментарию Ракеша Шармы я мог решить это, используя флаг -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 для строковых манипуляций.

Edit: Добавлено ((i++)) чтобы предотвратить бесконечный цикл (спасибо комментарию Kusalananda ).