Mit einem kleinen Perl-Skript, das angewiesen wird, zeilenweise ( -l -pe
) Ersetzungen für die als Argumente übergebenen Dateien durchzuführen, können Sie etwas Grobes tun -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
Mögliche Verbesserungen wären, Teile der Eingabeaufforderung einzufärben und Dinge wie "Alle Vorkommen in der aktuellen Datei ersetzen" zu unterstützen. Es wäre schwieriger, jedes Vorkommen in einer Zeile separat aufzufordern.
Zweiter Teil, passend zu den Dateien. Wenn nicht zu viele Dateien beteiligt sind und Sie zsh ausführen, können Sie alle Dateien im aktuellen Verzeichnis und seinen Unterverzeichnissen rekursiv abgleichen:
perl -i -l -pe '…' **/*(.)
Wenn Ihre Shell bash ≥4 ist, können Sie ausführen perl … **/*
, dies führt jedoch zu falschen Fehlermeldungen, da sed versucht (und fehlschlägt), in Verzeichnissen ausgeführt zu werden. Wenn Sie das Ersetzen nur in einer Reihe von Dateien wie C-Dateien durchführen möchten, können Sie die Übereinstimmungen einschränken (dies funktioniert entweder in Bash ≥4 oder zsh):
perl -i -l -pe '…' **/*.[hc]
Wenn Sie eine genauere Kontrolle darüber benötigen, welche Dateien Sie ersetzen, oder Ihre Shell nicht über das rekursive Verzeichnisvergleichskonstrukt **
verfügt oder wenn Sie zu viele Dateien haben und den Fehler "Befehlszeile zu lang" erhalten, verwenden Sie find
. Um beispielsweise eine Ersetzung in allen Dateien mit dem Namen *.h
oder *.c
im aktuellen Verzeichnis und seinen Unterverzeichnissen durchzuführen (auf älteren Systemen müssen Sie diese möglicherweise \;
anstelle des +
Zeilenendes verwenden (das +
Formular ist schneller, aber nicht überall verfügbar).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
Davon abgesehen würde ich mich an einen interaktiven Editor halten, wenn Sie Interaktion benötigen. Gert hat in Vim einen Weg dazu aufgezeigt , erfordert jedoch das Öffnen aller Dateien, die Sie durchsuchen möchten. Dies kann ein Problem sein, wenn viele vorhanden sind.
In Emacs können Sie Folgendes tun:
- Sammeln Sie die Dateinamen mit
M-x find-name-dired
(geben Sie ein Verzeichnis auf oberster Ebene an) oder M-x find-dired
(geben Sie eine beliebige find
Befehlszeile an).
- Drücken Sie im resultierenden dired- Puffer,
t
um alle Dateien zu markieren, und dann Q
( dired-do-query-replace-regexp
) , um einen Ersatz mit Aufforderung für die markierten Dateien durchzuführen.
s/from/to/g
mit einem Formatierungsfehler danach gelesen , anstatt dens/from/to/gc
Schwerpunkt auf das zu legen,c
was Sie zu schreiben versucht hatten (das können Sie mit Markdown nicht tun, Sie könnten es tun<code>
und<strong>
HTML-Tags).