Вы можете сделать что-то грубое с небольшим скриптом Perl, который инструктируется выполнять построчную замену -l -peфайлов, передаваемых в качестве аргументов ( -i):
perl -i -l -pe '
if (/from/) { # is the source text present on this line?
printf STDERR ("%s: %s [y/N]? ", $ARGV, $_); # display a prompt
$r=<STDIN>; # read user response
if ($r =~ /^[Yy]/) { # if user entered Y:
s/from/to/g; # replace all occurences on this line
}' /path/to/files
Возможные улучшения будут состоять в том, чтобы раскрасить части приглашения и поддерживать такие вещи, как «заменить все вхождения в текущем файле». Отдельно подсказывать для каждого вхождения на линии будет сложнее.
Вторая часть, сопоставление файлов. если задействовано не слишком много файлов и вы используете zsh, вы можете рекурсивно сопоставить все файлы в текущем каталоге и его подкаталогах:
perl -i -l -pe '…' **/*(.)
Если ваша оболочка bash ≥4, вы можете запустить perl … **/*, но это приведет к ложным сообщениям об ошибках, потому что sed будет пытаться (и не сможет) запускаться в каталогах. Если вы хотите выполнить замену только в наборе файлов, таких как файлы C, вы можете ограничить совпадения (это работает в bash ≥4 или zsh):
perl -i -l -pe '…' **/*.[hc]
Если вам нужен более точный контроль над тем, какие файлы вы заменяете, или у вашей оболочки нет рекурсивной конструкции соответствия каталогов **, или если у вас слишком много файлов и выдается ошибка «слишком длинная командная строка», используйте find. Например, чтобы выполнить замену во всех именованных файлах *.hили *.cв текущем каталоге и его подкаталогах (в старых системах вам может потребоваться использовать \;вместо +конца строки ( +форма быстрее, но не везде доступна).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
При этом я бы предпочел интерактивный редактор, если вам нужно взаимодействие. Герт показал путь к этому в Vim , хотя для этого нужно открыть все файлы, которые вы хотите найти, что может быть проблемой, если их много.
В Emacs вот как вы можете это сделать:
- Соберите имена файлов с помощью
M-x find-name-dired(укажите каталог верхнего уровня) или M-x find-dired(укажите произвольную findкомандную строку).
- В полученном буфере с задержкой нажмите,
tчтобы пометить все файлы, затем Q( dired-do-query-replace-regexp), чтобы выполнить замену с предложением пометить файлы.
s/from/to/gс ошибкой форматирования после нее, а неs/from/to/gcс акцентом на то,cкак вы пытались написать (вы не можете сделать это с Markdown, вы можете сделать это с<code>и<strong>HTML-теги).