Можно расширить строки в ударе с помощью обратной косой черты в конце строки как это:
export PATH=/path/A:\
/path/B:\
/path/C
Обратите внимание на то, что отсутствие пробела важно здесь.
Поэтому жемчуг читает текстовый файл одна строка за один раз и применяет шаблон замены к каждой строке - поэтому, если будет несколько случаев маркера в различных строках, то они будут все заменены.
Для замены просто первого вхождения в файле можно добавить -0
опция, которая устанавливает входной разделитель записей на нулевой символ и заставляет жемчуг считать целый файл прежде, чем сделать замену.
s/$f/$g/
заменяет первое вхождение $f
$g
на каждой строке. Если Вы хотите заменить только первое вхождение $f
в целом файле необходимо сказать так. Это - то, в чем Вы в конечном счете выполнили sed
с 0,/$f/ s/$f/$g/
(замена $f
$g
до и включая первое вхождение $f
). В Perl можно записать это в более подробном, но более легком для понимания пути как это (примечание: посмотрите ниже для заключения в кавычки проблем):
perl -i -pe 'if ($n==0) {s/$f/$g/; $n=1;} elsif ($n==1) {s/$f/$h/; $n=2}'
Ваш код страдает от многочисленных проблем заключения в кавычки; Вы столкнетесь с проблемой, если Ваши имена файлов будут содержать пробел, globbing символы или непечатные символы (такие как последовательности байта, которые не существуют в текущей локали). К счастью, эти проблемы легко устранить.
Во-первых, некоторые универсальные проблемы оболочки. Всегда подстановки переменных двойной кавычки "$foo"
и замены команды "$(foo)"
если Вы не знаете, почему необходимо оставить их, закрыл кавычки. Если Вы оставляете их, закрыл кавычки, результат разделяется на отдельные слова везде, где он содержит пробел, и каждое слово рассматривают как шаблон шарика. Таким образом, если переменная, оказывается, не содержит разделенный от пробела список шаблонов шарика, поместите двойные кавычки вокруг этого. Кроме того, я рекомендую использовать $(…)
вместо `…`
; они эквивалентны, за исключением того, что вложенное заключение в кавычки внутри `…`
ненадежно (также, `
легко перепутан с '
).
Не анализируйте вывод ls
. Если необходимо действовать на все файлы в каталоге, оболочка имеет встроенную конструкцию, которая работает: globbing. Вместо $(ls /path/to/directory)
, записать /path/to/directory/*
. Это генерирует имена файлов с путем к каталогу; это почти всегда, в чем Вы нуждаетесь так или иначе, и если Вы не делаете, можно или звонить cd
заранее или снимите все или часть каталога. Ниже, я использую ${f#*/*/}
, что означает $f
с самым коротким соответствием префикса */*/
неизолированный.
for f in .templates/template_text/*; do
g=$(cat "$f")
h=$(cat ".templates/template_html/${f#*/*/}")
find to_process/ -type f …
done
С find
, можно использовать более простую конструкцию -exec
, хотя -print0
объединенный с xargs -0
работы также. Не использовать xargs
без -0
, поскольку это ожидает вход, заключенный в кавычки специфическим способом который find
не производит.
find to_process/ -type f -exec perl … {} +
Следующий выпуск - то, что Вы вставляете строки $f
, $g
и $h
непосредственно в Вашем sed или регулярном выражении жемчуга. Это неправильно: они переменная не содержат регулярное выражение с разделителем (/
в обоих случаях) заключенный в кавычки. С sed необходимо было бы сделать передачу заключения в кавычки на строках, добавив обратную косую черту перед любой из /*.\[
в $f
и перед любой из \&/
в $g
и $h
. С Perl существует более простой путь: передайте значения через среду и обязательно скажите Perl, который, что Вы имеете, строка и не regexp.
export f g h
find to_process/ -type f -exec perl -i -e '
if ($n==0) {s/\Q$ENV{f}/$ENV{g}/; $n=1;}
elsif ($n==1) {s/\Q$ENV{f}/$ENV{h}/; $n=2}}
' {} +