Вы можете сделать что-то грубое с небольшим скриптом 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-теги).