Может кто-нибудь предложить элегантный способ сделать это?
Входные данные:
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
Это работало, но индекс просто продолжал увеличиваться от одного к другому файлу. Я хотел бы сбросить это до 1 при изменении на новый файл. Есть хорошие предложения?
find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} +
работает, но он заменил все остальные файлы не должны быть заменены. Я предпочитаю просто заменить файлы *.txt
только.
test instant ()
?Ответы:
или с GNU
awk
:Чтобы редактировать файлы на месте, добавьте
-i
параметр вperl
:Или рекурсивно:
Пояснения
-p
обрабатывать входные данные построчно, оценивать переданные выражения-e
для каждой строки и распечатывать их. Для каждой строки мы подставляем (используяs/re/repl/flags
оператор)instant
для себя ($&
) и увеличенное значение переменной++$n
.g
Флаг , чтобы сделать замену во всем мире ( а не только один раз), иe
таким образом , что замена интерпретируется как PERL код для электронной valuate (не фиксированная строка).Для редактирования на месте, когда один вызов perl обрабатывает более одного файла, мы хотим
$n
выполнить сброс для каждого файла. Вместо этого мы используем$n{$ARGV}
(где$ARGV
находится текущий обрабатываемый файл).Тот
awk
заслуживает немного объяснения.Мы используем способность GNU
awk
разделять записи на произвольные строки (даже регулярные выражения). С помощью-vRS=instant
, мы устанавливаем raraecord s̲eparator вinstant
.RT
переменная, которая содержит то, что было сопоставленоRS
, как правило,instant
за исключением последней записи, где она будет пустой строкой. Во входных данных выше записи ($0
) и терминаторы записи (RT
): ([$0|RT]
):Таким образом, все, что нам нужно сделать, это вставить увеличивающийся номер в начале каждой записи, кроме первой.
Что мы и делаем выше. Для первой записи
n
будет пусто. Мы устанавливаем ORS ( o̲utput r̲ecord s̲eparator ) в RT, чтобыawk
печататьn $0 RT
. Это происходит со вторым выражением (++n
), которое является условием, которое всегда оценивается как истина (ненулевое число), и, следовательно, действие по умолчанию (печати$0 ORS
) выполняется для каждой записи.источник
sed
действительно не лучший инструмент для работы, вы хотите что-то с лучшими возможностями сценариев. Вот несколько вариантов:Perl
В
-p
означает «печать каждую строка» после применения любого сценария даются с-e
. В-00
очереди на режиме «пункт» так записи (строки) определяются путем последовательным переводом строки (\n
) символы, это позволяет ему иметь дело с двойными отстоящими друг от друга линий правильно.$&
последний сопоставленный шаблон и$.
номер текущей строки входного файла. Функцияe
ins///e
позволяет мне вычислять выражения в операторе подстановки.awk (предполагается, что ваши данные точно такие, как показано, с тремя разделенными пробелами полями)
Здесь мы увеличиваем
k
переменную,k
только если текущая строка не пуста, и/./
в этом случае мы также выводим необходимую информацию. Пустые строки печатаются как есть.различные снаряды
Здесь каждая входная строка автоматически разбивается на пробельных и поля сохраняются как
$a
,$b
и$c
. Затем, в течение цикла,$c
увеличивается на единицу для каждой строки , для которых$a
не является пустым , и это текущее значение выводится рядом со вторым полем,$b
.ПРИМЕЧАНИЕ: все вышеприведенные решения предполагают, что все строки в файле имеют одинаковый формат. Если нет, то ответ @ Stephane - это путь.
Для работы со многими файлами и предположения, что вы хотите сделать это для всех файлов в текущем каталоге, вы можете использовать это:
ОСТОРОЖНО: Это предполагает , что простые имена файлов без пробелов, в случае необходимости иметь дело с чем - то более сложным, пойти (при условии
ksh93
,zsh
илиbash
):источник
Если вы хотите решить эту проблему,
sed
вы можете использовать что-то вроде этого (вbash
):или более портативное решение будет:
источник