Ви можете зробити щось неочищене за допомогою невеликого сценарію 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).