Заменить строку последовательным индексом

Может ли кто-нибудь предложить элегантный способ сделать это?

Входные данные:

test instant () test instant () ... test instant () //total 1000 lines 

выход должен быть:

 test instant1 () test instant2 () test instant1000() 

Пустые строки находятся в моих входных файлах, и есть много файлов в одном каталоге, которые мне нужно обрабатывать сразу.

Я попробовал это, чтобы заменить многие файлы в одном каталоге и не работал.

 for file in ./*; do perl -i -000pe 's/instance$& . ++$n/ge' "$file"; done 

ошибки:

 Substitution replacement not terminated at -e line 1. Substitution replacement not terminated at -e line 1. 

и я также пробовал это: perl -i -pe 's/instant/$& . ++$n/ge' *.vs perl -i -pe 's/instant/$& . ++$n/ge' *.vs

Он работал, но индекс просто увеличивался от одного к другому. Я хотел бы сбросить его до 1 для файла diff. любые хорошие предложения?

 find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} + 

но он заменил все другие файлы, которые не должны быть заменены. Я предпочитаю просто заменять файлы только «* .txt».

2 Solutions collect form web for “Заменить строку последовательным индексом”

 perl -pe 's/instant/$& . ++$n/ge' 

или с GNU awk :

 awk -vRS=instant '{$0=n$0;ORS=RT}++n' 

Чтобы редактировать файлы на месте, добавьте параметр -i в perl :

 perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' ./* 

Или рекурсивно:

 find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} + 

Пояснения

 perl -pe 's/instant/$& . ++$n/ge' 

-p – обрабатывать ввод строки за строкой, оценивать выражение, переданное -e для каждой строки, и печатать его. Для каждой строки мы подставляем (используя оператор s/re/repl/flags ) для себя ( $& ) и добавочное значение переменной ++$n . Флаг g должен сделать замену глобально (не только один раз), а e чтобы замена интерпретировалась как Perl-код для оценки e (не фиксированная строка).

Для редактирования на месте, где один вызов perl обрабатывает более одного файла, мы хотим, чтобы $n перезагружался в каждом файле. Вместо этого мы используем $n{$ARGV} (где $ARGV$ARGV обработанный файл).

awk заслуживает некоторого объяснения.

 awk -vRS=instant '{$0=n$0;ORS=RT}++n' 

Мы используем способность GNU awk отделять записи от произвольных строк (даже регулярных выражений). Когда -vRS=instant , мы устанавливаем разделитель записи на instant . RT – это переменная, которая содержит то, что соответствовало RS , так обычно, instant за исключением последней записи, где она будет пустой строкой. На входе выше записи ( $0 ) и терминаторы записи ( RT ) являются ( [$0|RT] ):

 [test |instant][ () test |instant][ () ... test |instant][ () //total 1000 lines|] 

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

Это то, что мы делаем выше. Для первой записи n будет пустым. Мы устанавливаем ORS ( разделитель выходной записи ) в RT, так что awk печатает n $0 RT . Он выполняет это на втором выражении ( ++n ), которое является условием, которое всегда оценивает значение true (ненулевое число), и поэтому для каждой записи выполняется действие по умолчанию (для печати $0 ORS ).

sed действительно не лучший инструмент для работы, вам нужно что-то с лучшими возможностями сценариев. Вот несколько вариантов:

  • Perl

     perl -000pe 's/instant/$& . $./e' file 

    -p означает «печатать каждую строку» после применения любого скрипта с -e . -000 включает «режим абзаца», поэтому записи (строки) определяются последовательными символами новой строки ( \n ), это позволяет правильно обрабатывать строки с двойным интервалом. $& – последний сопоставленный шаблон и $. – текущий номер строки входного файла. e in s///e позволяет оценить выражения в операторе подстановки.

  • awk (это предполагает, что ваши данные точно такие, как показано, с тремя полями, разделенными пробелами)

     awk '{if(/./) print $1,$2 ++k,$3; else print}' file 

    Здесь мы увеличиваем k переменную k только в том случае, если текущая строка не пуста /. / И в этом случае мы также печатаем необходимую информацию. Пустые строки печатаются как есть.

  • различные раковины

      n=0; while read -rabc; do if [ "$a" ] ; then (( n++ )) printf "%s %s%s %s\n" "$a" "$b" "$n" "$c" else printf "%s %s %s\n" "$a" "$b" "$c" fi done < file 

    Здесь каждая строка ввода автоматически разбивается на пробелы, а поля сохраняются как $a , $b и $c . Затем в цикле $c увеличивается на 1 для каждой строки, для которой $a не пуст, и текущее значение печатается рядом со вторым полем, $b .

ПРИМЕЧАНИЕ. Все вышеупомянутые решения предполагают, что все строки в файле имеют один и тот же формат. Если нет, @ ответ Стефана – это путь.


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

 for file in ./*; do perl -i -000pe 's/instant/$& . $./e' "$file"; done 

ОСТОРОЖНО: это предполагает простые имена файлов без пробелов, если нужно иметь дело с чем-то более сложным, идите (предполагая ksh93 , zsh или bash ):

 find . -type f -print0 | while IFS= read -r -d ''; do perl -i -000pe 's/instant/$& . $./e' "$file" done 
  • grep -A с обратной совпадением распечатывает только несоответствие в поле после
  • Сценарий Bash для извлечения некоторой информации из HTML-страниц Ebay
  • Искать текст в Linux, но не отображать полную строку в результатах
  • Как найти и заменить только определенное слово (которое находится в конце файла) с помощью команды оболочки?
  • Как получить путь, индекс строки и содержимое строки в оболочке bash?
  • метки тега sed
  • Создать в HTML из вывода скрипта bash
  • Извлечение строк между специальными символами
  • Как найти строку после регулярного выражения в одной строке текста?
  • Узнайте, на какой строке в текстовом файле соответствует слово
  • Греп для числа в строке
  • Interesting Posts

    Как удалить .deb, установленный с помощью dpkg?

    Как диагностировать надежную ненадежную связь?

    Как запустить последующие оболочки с правами root?

    Arch Linux: поиск зависимостей сборки, чтобы они могли быть превращены в зависимости от AUR

    Как я могу сказать, какое приложение * запрашивает доступ к gnome-keyring / Seahorse?

    Как заставить rpm проверять зависимости во время обновления?

    Перенаправление стандартного вывода и стандартная ошибка для одного файла

    bash: как мне записать содержимое, закодированное в base64, в файл на указанную строку

    Потребляемая мощность сетевого адаптера Ethernet на ноутбуке?

    Помогите понять интерфейсы в Backtrack

    Что случилось с этим правилом udev?

    Как отображать время безотказной работы в баре i3status?

    Возврат перенаправления и вывода строки и понимания

    Могу ли я перенести файл в папку (на удаленном сервере), доступную для записи только через root (через sudo)?

    grep для соответствия шаблону, только если после него есть несколько буквенно-цифровых символов

    Linux и Unix - лучшая ОС в мире.