Ich bin auf eine Frage (zu SO selbst) gestoßen, bei der OP die Operation bearbeiten und in Input_file (s) selbst speichern muss.
Ich weiß, dass wir für eine einzelne Eingabedatei Folgendes tun können:
awk '{print "test here..new line for saving.."}' Input_file > temp && mv temp Input_file
Nehmen wir nun an, wir müssen Änderungen im gleichen Dateiformat vornehmen (hier wird .txt angenommen).
Was ich für dieses Problem versucht / gedacht habe: Sein Ansatz besteht darin, eine for-Schleife von TXT-Dateien zuawk
durchlaufen,und das Aufrufen von Singleist ein schmerzhafter und NICHT empfohlener Prozess, da unnötige CPU-Zyklen verschwendet werden und für mehr Dateien mehr langsam.
Was könnte hier also möglicherweise getan werden, um eine Inplace-Bearbeitung für mehrere Dateien mit einer NON GNU durchzuführen, awk
die die Inplace-Option nicht unterstützt? Ich habe auch diesen Thread durchgearbeitet. Speichern Sie Änderungen an Ort und Stelle mit awk, aber es gibt nicht viel für NON GNU awk vice und das Ändern mehrerer Dateien an awk
sich, da ein Nicht-GNU awk keine inplace
Option dazu hat.
HINWEIS: Warum ich einbash
Taghinzufüge,da ich in meinem Antwortteil Bash-Befehle verwendet habe, um temporäre Dateien in ihre tatsächlichen Input_file-Namen umzubenennen, um sie hinzuzufügen.
BEARBEITEN: Gemäß dem Kommentar von Ed Sir, der hier ein Beispiel für Beispiele hinzufügt, obwohl der Zweck des Codes dieses Threads auch für die allgemeine Bearbeitung an Ort und Stelle verwendet werden könnte.
Beispiel-Eingabedatei (en):
cat test1.txt
onetwo three
tets testtest
cat test2.txt
onetwo three
tets testtest
cat test3.txt
onetwo three
tets testtest
Beispiel für die erwartete Leistung:
cat test1.txt
1
2
cat test2.txt
1
2
cat test3.txt
1
2
awk
(möglicherweise in einer Subshell) oder einer{...}
geschlossenen Gruppe und schreiben Sie die Ergebnisse in die gewünschte Ausgabedatei (entweder für jede Eingabedatei). oder eine kombinierte Datei für alle Eingabedateien). Dann leiten Sie einfach die Ausgabe der Unterschale oder der in Klammern eingeschlossenen Gruppe in die aktuelle Datei um, in die geschrieben wird? Das einfache Einfügen einer Zeichenfolge von Eingabedateien nach demawk
Befehl würde alle Dateien (oder ähnliches) nacheinander verarbeiten.awk {..} file1 .. fileX
Schreiben der geänderten Datei als z. B.temp01
und in Ihrer nächsten Iteration während der Verarbeitung der nächsten Datei verwenden Sie amv -f tmp01 input01
, um die Eingabedatei mit den geänderten Daten zu überschreiben. oder (2) schreiben Sie einfach ein neues Verzeichnis von./tmp/tmp01 ... ./tmp/tmp0X
während der Ausführung desawk
Skripts und folgen Sie mit einer Schleife über die Dateien im./tmp
Verzeichnis und z. B.mv -f "$i" "input_${i##*[^0-9]}"
(oder welche Erweiterung Sie benötigen, um die alten Eingabedateien zu ersetzen.awk
die vollständige Code-Vervollständigung tun. Die 2. Option ist fast die gleiche, die ich in meinem Vorschlag verwende Seien Sie dankbar, wenn Sie Ihre Gedanken über diese Lösung wissen lassen könnten, Sir.Antworten:
Da das Hauptziel dieses Threads darin besteht, SAVE in NON GNU zu ersetzen
awk
, veröffentliche ich zuerst seine Vorlage, die jedem bei jeder Art von Anforderung hilft. Sie müssen ihren Code hinzufügen / anhängenBEGIN
und einenEND
Abschnitt in ihren Code einfügen, wobei ihr Haupt-BLOCK gemäß ihrem beibehalten wird Anforderung und es sollte dann die Inplace-Bearbeitung durchführen:HINWEIS: Im Folgenden wird die gesamte Ausgabe in die Ausgabedatei geschrieben. Wenn Sie also etwas in die Standardausgabe drucken möchten, fügen Sie bitte nur eine
print...
Anweisung hinzu, ohne die> (out)
folgendenSchritte auszuführen.Generische Vorlage:
Spezifische Lösung der bereitgestellten Probe:
Ich habe mir einen folgenden Ansatz
awk
ausgedacht (für zusätzliche Beispiele folgt mein Ansatz, um dies zu lösen und die Ausgabe in Input_file selbst zu speichern).HINWEIS: Dies ist nur ein Test zum Speichern der bearbeiteten Ausgabe in den Eingabedateien selbst. Sie können den Abschnitt BEGIN zusammen mit dem Abschnitt END in ihrem Programm verwenden. Der Hauptabschnitt sollte den Anforderungen einer bestimmten Frage selbst entsprechen.
Faire Warnung: Da bei diesem Ansatz eine neue temporäre Out-Datei im Pfad erstellt wird, sollten Sie sicherstellen, dass genügend Speicherplatz auf den Systemen vorhanden ist. Letztendlich werden jedoch nur die wichtigsten Eingabedateien gespeichert, während des Betriebs wird jedoch Speicherplatz auf dem System / Verzeichnis benötigt
Es folgt ein Test für den obigen Code.
Programmausführung mit einem Beispiel: Nehmen wir an, es folgen die
.txt
Input_file (s):Wenn wir nun folgenden Code ausführen:
HINWEIS: Ich habeabsichtlich einen Abschnitt
ls -lhtr
in densystem
Abschnitt eingefügt, um zu sehen, welche Ausgabedateien erstellt werden (temporäre Basis), da diese später in ihren tatsächlichen Namen umbenannt werden.Wenn ein
ls -lhtr
After-awk
Script ausgeführt wird, können nur.txt
Dateien darin angezeigt werden.Erläuterung: Fügen Sie hier eine detaillierte Erläuterung des obigen Befehls hinzu:
quelle
FNR==1
Block löschen , können Sie die Änderungen weiterhin an Ort und Stelle speichern. Wieawk 'FNR==1{system("rm " FILENAME)} {print "new lines" > FILENAME}' files...
. Dies ist überhaupt nicht zuverlässig (ein vollständiger Datenverlust ist wahrscheinlich), funktioniert aber meistensIch würde wahrscheinlich so etwas machen, wenn ich versuchen würde, dies zu tun:
Ich hätte es vorgezogen, zuerst die Originaldatei in die Sicherung zu kopieren und dann die Änderungen am Original zu speichern, aber dies würde den Wert der Variablen FILENAME für jede Eingabedatei ändern, was unerwünscht ist.
Beachten Sie, dass Sie Originaldateien mit dem Namen
whatever.bak
oderwhatever.new
in Ihrem Verzeichnis mit temporären Dateien überschreiben würden, sodass Sie auch dafür einen Test hinzufügen müssten. Ein Aufruf zummktemp
Abrufen der temporären Dateinamen wäre robuster.Die weitaus nützlichere Sache in dieser Situation wäre ein Tool, das jeden anderen Befehl ausführt und den Bearbeitungsteil "Inplace" ausführt, da dies verwendet werden könnte, um "Inplace" -Bearbeitung für POSIX sed, awk, grep, tr, was auch immer und bereitzustellen Sie müssen die Syntax Ihres Skripts nicht
print > out
jedes Mal ändern, wenn Sie einen Wert drucken möchten. Ein einfaches, fragiles Beispiel:die Sie wie folgt verwenden würden:
Ein offensichtliches Problem bei diesem
inedit
Skript ist die Schwierigkeit, die Eingabe- / Ausgabedateien getrennt vom Befehl zu identifizieren, wenn Sie mehrere Eingabedateien haben. Das obige Skript geht davon aus, dass alle Eingabedateien am Ende des Befehls als Liste angezeigt werden und der Befehl einzeln ausgeführt wird. Dies bedeutet jedoch natürlich, dass Sie ihn nicht für Skripte verwenden können, für die zwei oder mehr Dateien erforderlich sind eine Zeit, zB:oder Skripte, die Variablen zwischen Dateien in der Arg-Liste festlegen, z.
Machen Sie es robuster als Übung für den Leser, aber sehen Sie sich die
xargs
Zusammenfassung als Ausgangspunkt dafür an, wie ein Robustesinedit
funktionieren müsste :-).quelle
Die Shell-Lösung ist einfach und wahrscheinlich schnell genug:
Suchen Sie nur dann nach einer anderen Lösung, wenn Sie eindeutig nachgewiesen haben, dass dies zu langsam ist. Denken Sie daran: Vorzeitige Optimierung ist die Wurzel allen Übels.
quelle