Bash: So holen Sie einige Zeilen aus einer Datei und speichern die Ausgabe in einer anderen Datei [geschlossen]
Ich habe eine Protokolldatei wie diese
$ cat build.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
So generieren Sie wie neu analysierte Protokolle, sodass die Ausgabe des neuen Dateiprotokolls folgendermaßen aussieht:
$ cat parsed.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
Als ob Sie nur den letzten Fortschritt [ 60% 60920/101076]
bis zum Ende der Datei erhalten, indem Sie vielleicht grep, sed oder irgendetwas verwenden. Vielen Dank
Antworten
Hier ist ein Perl:
$ perl -0777 -lne 'print $1 if /(^\[[^[]*\z)/m' file
Oder eine Perlpfeife:
$ perl -E 'say reverse <>' file | perl -lpE 'if (/^\[/){ say; last}' | perl -E 'say reverse <>'
Für eine können awk
Sie tun:
$ awk 'BEGIN{RS="\\["}END{print "[" $0}' file
Natürlich können Sie wissen, dass, wenn der Fehler immer 3 Zeilen beträgt, die einfachste nur verwendet wird tail
:
$ tail -n 3 file
Alle drucken:
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
$ cat build.log ........ [ 60% 60917/101076] AAPT2 compile .... [ 60% 60918/101076] AAPT2 compile .... [ 60% 60919/101076] AAPT2 compile .... [ 60% 60920/101076] AAPT2 compile .... ninja: build stopped: subcommand failed. 21:41:22 ninja failed with: exit status 1 $ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' build.log
........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
awk
ist das richtige Werkzeug für solche Dinge. Hier prüfen wir, ob das 2. Feld mit dem 2. Feld der vorherigen Zeile übereinstimmt, und drucken, wenn dies der Fall ist. Speichern Sie dann die vorherige Zeile und wiederholen Sie den Vorgang. Drucken Sie immer die letzte Zeile der Eingabe.
Dies könnte für Sie funktionieren (GNU sed):
sed '/^\[/h;//!H;$!d;x' file
Wenn eine Zeile beginnt, [
speichern Sie sie im Haltebereich (überschreiben Sie alles, was zuvor dort vorhanden war).
Andernfalls hängen Sie die aktuelle Zeile an den Haltebereich an.
Löschen Sie alle Zeilen außer der letzten.
Wechseln Sie am Ende der Datei in den Haltebereich und drucken Sie den Inhalt.
Sie haben manchmal kein Glück, wenn Sie diese Art von Filter ausführen möchten, ohne die Reihenfolge der Zeilen ändern zu müssen. Und wenn diese Zeilen nicht am Anfang der Datei, oder am Ende geschrieben: tac
, sort
und uniq
würden nicht die richtigen Werkzeuge sein.
Hier ist eine Lösung mit awk
:
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log
..........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
Die lesbare und erklärte Version:
# a function to append an element to an array dynamically
function push(a,e) {
a[length(a)+1] = e
}
BEGIN {
split("", lines); # initializing an array
to_replace="toreplace"; # you can change the replace key if you want
exists=0
}
{
if ($0 ~ "^\\[ [0-9]+%"){ # matching all percentages/progression lines, regardless of their values ll=$0;
if (exists <= 0) {
exists++;
push(lines, to_replace)
}
} else {
push(lines, $0)
}
}
END {
for (e in lines) {
if (lines[e] == to_replace) {
print ll
} else {
print lines[e]
}
}
}
Der Unterschied zu den William Pursel-Lösungen besteht darin, dass Ihre Prozentsätze steigen. Lassen Sie uns den Unterschied im Verhalten in diesem Fall sehen:
$ cat test.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log
..........
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
$ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' test.log
..........
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
Sie können also wählen, ob Sie nur die letzte Fortschrittslinie beibehalten möchten, auch wenn der Prozentsatz nicht gleich ist, oder ob Sie nur die Linien filtern möchten, die denselben Prozentsatz mehrmals haben.
Wenn garantiert ist, dass die erste Zeile, die Sie ausgeben möchten, die letzte Zeile ist, mit der begonnen wird [
, können Sie dies tun, wobei im Wesentlichen alles vom Anfang der Datei bis zur letzten Zeile , der [
ein Zeilenumbruch vorausgeht, durch eine einzelne ersetzt wird [
:
sed -z 's/.*\n\[/[/' file
Angenommen, die ...
Zeile am Anfang Ihrer Beispieleingabe repräsentiert mehr führende [...] ...
Zeilen:
$ awk '/^\[/{p=$0 ORS; next} {print p $0; p=""}' build.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
Wenn diese Annahme falsch ist, bearbeiten Sie bitte Ihre Frage, um ein minimales, vollständiges und überprüfbares Beispiel anzuzeigen - eines mit nur repräsentativen Werten, nicht ...
s.