Когда я пытаюсь использовать номер строки из переменной в 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.
Это не удается, потому что материал после <<< получает список правильных номеров строк в исходном файле .
Затем вы редактируете файл несколько раз, вставляя дополнительные строки .
Таким образом, каждому 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