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

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

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

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 
  • Удалите строку, используя определенные значения (-)
  • Как выполнить действие только в первой строке?
  • Сценарий Bash для извлечения некоторой информации из HTML-страниц Ebay
  • Усеченный результат, возвращаемый JOIN
  • Как удалить все вхождения списка слов из текстового файла?
  • Как «grep» для длины строки * not * в заданном диапазоне?
  • Заменить шаблон в файле с шаблоном во втором файле
  • Почему эта команда xargs не работает?
  • найти и заменить строку в файле без использования временного файла с SED
  • Как найти строки, содержащие более 100 символов, и содержит «if»?
  • array выводит все испорченные?
  • Interesting Posts

    Как проверить с вывода «uname -a», установленная ОС Solaris является openSolaris или нет

    Как заставить мой ELF работать как с новой, так и с старой версией glibc?

    Управление отображаемыми файлами

    Что может привести к тому, что не показывать что-то в пути?

    Глобальный / etc / profile setenv или экспорт, перезаписывающий пользовательские настройки в .profile

    Bash globs как аргументы без файла. Пример: apt-get remove pkg- *

    Vim продолжает показывать сообщение об ошибке в цветовой схеме без каких-либо причин

    Как пассивно захватывать из сокетов домена Unix (мониторинг сокетов AF_UNIX)?

    ulimit против лимита на FreeBSD 8.3

    Чтение и добавление в файл одновременно с сохранением конца строки

    Как настроить правила iptables, чтобы разрешить скайп

    Скорость колесика мыши слишком чувствительна

    Как регистрировать вывод в файл журнала с помощью runit

    Спецификация RPM для проекта C / C ++: как я могу узнать, как заполнять поля Requires и BuildRequires?

    Разница между yum update vs yum install

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