Ist es möglich , zu verwenden , gawk
s‘ -i inplace
Option und auch drucken Dinge stdout
?
Wenn ich beispielsweise eine Datei aktualisieren wollte und Änderungen vorgenommen wurden, den Namen der Datei und die geänderten Zeilen zu drucken, stderr
könnte ich so etwas tun
find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +
Aber gibt es eine Möglichkeit, stdout
diesen Block zu verwenden , oder eine sauberere Möglichkeit, diesen Block in den alternativen Stream zu drucken?
find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;
Sie verwenden awk nur, um die Dateien zu bearbeiten, die tatsächlich Linien enthalten, die diesem Muster entsprechen.grep
kann. Mein erster Instinkt ist, zu vermeiden, dass die Datei zweimal "verarbeitet" werden muss, aber ich wäre überhaupt nicht überrascht, wenn sie tatsächlich schneller ist. Es zeigt nur, warum ich bei Profilierungsaufgaben meinem Bauch vertrauen kann-print -exec gawk
wird nicht mehr ausgeführt) und 2) sie stoppt bei der ersten Übereinstimmung, es sei denn, die erste Übereinstimmung ist auf der In der letzten Zeile verarbeiten Sie immer noch nicht die gesamte Datei zweimal (es ist eher 1.X-mal). Wenn es sogawk -i inplace
funktioniertsed -i
, wird die Datei trotzdem an Ort und Stelle bearbeitet - dh Zeitstempel, Inode usw. werden aktualisiert, auch wenn nichts zu bearbeiten war ...Antworten:
Sie sollten
/dev/stderr
oder/dev/fd/2
anstelle von verwenden/proc/self/fd/2
.gawk
Handles/dev/fd/x
und/dev/stderr
für sich (unabhängig davon, ob das System diese Dateien hat oder nicht).Wenn Sie eine:
gawk
tut einewrite(2, "x\n")
, während, wenn Sie tun:da es nicht
/proc/self/fd/x
speziell behandelt , tut es ein:Erstens
/proc/self/fd
ist Linux spezifisch und unter Linux sind sie problematisch. Die beiden oben genannten Versionen sind nicht gleichwertig, wenn stderr einer regulären oder anderen durchsuchbaren Datei oder einem Socket (für den letzterer fehlschlagen würde) entspricht (ganz zu schweigen davon, dass ein Dateideskriptor verschwendet wird).Davon abgesehen, wenn Sie auf das ursprüngliche Standard schreiben müssen, müssen Sie es in einem anderen Feld speichern, wie:
gawk
leitet stdout mit in-place in die Datei um. Es wird benötigt, weil Sie zum Beispiel möchten:um die
uname
Ausgabe in der zu speichernfile
.quelle
Just for fun, ein alternativer Ansatz nur POSIX mit Funktionen von
find
,sh
,grep
und (vor allem)ex
:(Alle Zeilenumbrüche im obigen Befehl sind optional; sie können zu einem Einzeiler zusammengefasst werden.)
Oder wohl leserlicher:
:) :)
(Dieser Befehl ist nicht getestet. Änderungen sind willkommen, wenn ich irgendwelche Fehler gemacht habe.)
quelle