sed не заменяет переменную в цикле while

Когда я пытаюсь использовать номер строки из переменной в sed, он работает индивидуально, но когда то же самое делается с помощью цикла while, он не работает.

напр.

cat file
den 
run
ten
run
fan

linenumber=2
replacetext=34
sed -i ""$linenumber"s/run/run\n"$replacetext"/" file

Output:
cat file
den
run
34
ten
run
fan

Описанное выше работает, и команда sed генерируется после раскрытия переменной.

Но когда я использую то же самое в цикле while, он работает только для первого экземпляра, а не для всех, поскольку я хотел заменить все экземпляры увеличивающимся номером строки, используя чистое решение sed. Решение Awk или Perl не требуется.

напр.

replacetext=1
while read in; do replacetext=$((replacetext++)) && sed ""$in"s/run/run\n"$replacetext"/" file; done <<< "$(cat file | grep 'run' -n | cut -f1 -d ':')"

Ожидаемый результат: текст совпадения будет заменен самим собой, за которым следует перевод строки и увеличивающееся число.

den 
run
2
ten
run
3
fan

Полученный результат:

den
run
2
ten
run
fan

Пожалуйста, требуется только решение на основе sed. И я хотел знать, какое необычное поведение происходило в цикле while, когда он не работал. Поскольку переменной цикла присваивается значение номера строки, а затем этот номер строки используется в sed для замены macthed текста в этой строке самим собой, за которым следует новая строка и увеличивающееся число.

Похоже, что Sed работает, когда указан тот же номер строки переменной, но не при использовании в цикле while.

0
28.06.2020, 16:03
1 ответ

Это не удается, потому что материал после <<< получает список правильных номеров строк в исходном файле .

Затем вы редактируете файл несколько раз, вставляя дополнительные строки .

Таким образом, каждому sed, кроме первого, сообщают неправильные номера строк для команды s///.

Одним из решений было бы перевернуть список номеров строк, чтобы правки не влияли на прежнюю нумерацию.

Это решение sed в одном конвейере, несколько необычное.

Первый sed получает номера строк, в которых найден Pattern, используя оператор =. nl ставит перед каждой строкой префикс порядкового номера :, например 3 10

Второй sed выводит sed-выражения :он преобразует каждую такую ​​строку в требуемое sed-редактирование, например:10 s/$/\n3/.

Третий sed собирает и применяет эти изменения со стандартного ввода и выполняет -редактирование файла на месте. В этом случае он редактирует сам себя.

Это сам скрипт:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'

sed -n -e "/${Pattern}/=" badSed |
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
    sed -i -f - badSed
 

Вот что он делает с собой:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'
1

sed -n -e "/${Pattern}/=" badSed |
2
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
3
    sed -i -f - badSed
4
2
18.03.2021, 23:24

Теги

Похожие вопросы