GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Awk aus verschiedenen Linien?

Ich versuche, einige Daten aus einer Datei zu extrahieren, die ständig aktualisiert wird, und ich habe herausgefunden, wie man zwei Zeichenfolgen mit grep filtert. Die Ausgabe sieht wie folgt aus:

!    total energy              =   -9744.24963670 Ry
     convergence has been achieved in 188 iterations
!    total energy              =   -9744.30001681 Ry
     convergence has been achieved in 140 iterations
!    total energy              =   -9744.33953891 Ry
     convergence has been achieved in 155 iterations
!    total energy              =   -9744.36584201 Ry
     convergence has been achieved in 164 iterations
!    total energy              =   -9744.37925372 Ry
     convergence has been achieved in 154 iterations
!    total energy              =   -9744.39185493 Ry
     convergence has been achieved in 153 iterations
!    total energy              =   -9744.39836617 Ry
     convergence has been achieved in 160 iterations

Nun möchte ich aus diesen Zeilen die Zahlen wie folgt extrahieren:
aus der Zeile, die mit beginnt! Ich möchte die Nummer in Spalte Nr. 5 und von der nächsten Zeile in der grep-Ausgabe möchte ich die Nummer in Spalte Nr. 6.
Als nächstes möchte ich, dass diese Zahlen in einer separaten Datei als zwei getrennte Spalten geschrieben werden:

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201

Ich dachte, dass ein Ansatz mit awk durch Schleifen durch all diese grep-Ergebnisse und dann durch Betrachten von ungeradzahligen Zeilen und Drucken von Spalte 5 und dann für gerade Zeilen Drucken von Spalte 6. Aber ich habe keine Ahnung, wie das geht.

Ich habe versucht, einzelne Ergebnisse separat in Variablen zu extrahieren:

var1=$(grep '!' input.file | awk '{print $5}')

und

var2=$(grep 'convergence has been achieved' input.file | awk '{print $6}')

und dann habe ich versucht, sie in eine Datei zu schreiben als:

echo $var1 $var2 > data.dat

Das Ergebnis ist jedoch nicht wie erwartet:

188                                                                                                                                                                                             
140
155
164
154
153
160 -9744.24963670
-9744.30001681
-9744.33953891
-9744.36584201
-9744.37925372
-9744.39185493
-9744.39836617

Ich weiß nicht, wie ich sie in der oben genannten Form schreiben soll. Da die Datei ständig aktualisiert wird, stelle ich mir vor, dass das Stück Code mit einer While-Schleife bis und einer Endbedingung kombiniert wird (ich weiß, wie man diesen letzten Teil macht)

Ich hoffe, ich habe das klar erklärt!

Akzeptierte Antwort:

awk Lösung:

awk 'v && NR==n{ print $6,v > "result.txt" }/^!/{ v=$5; n=NR+1 }' file
  • <condition1> { <statement> ... }<condition2>{ <statement> ... } – Bedingungen mit entsprechenden Aussagen werden nacheinander ausgewertet

  • /^!/{ v=$5; n=NR+1 } – auf eine Zeile, die mit ! beginnt – erfassen Sie den 5. Feldwert $5 und planen Sie die nächste Zeile Nummer NR+1 (Zuweisung an Variable n )

  • v && NR==n – wenn wir die 1. entscheidende Zahl v haben und die aktuelle Datensatznummer NR ist die benötigte "nächste Zeilennummer" n – drucke die Werte in die Datei result.txt

Die result.txt Dateiinhalt:

188 -9744.24963670
140 -9744.30001681
155 -9744.33953891
164 -9744.36584201
154 -9744.37925372
153 -9744.39185493
160 -9744.39836617

Linux
  1. Effizient die ersten paar Zeilen aus einer Textdatei entfernen?

  2. Lesen von Zeilen aus einer Datei mit Bash:Für Vs. Während?

  3. Linux-wc-Befehl

  4. Entfernen Sie leere Zeilen in einer Textdatei mit grep

  5. Drucken Sie die letzte Zeile einer Datei über die CLI

So entfernen Sie Zeilen aus einer Datei mit dem Sed-Befehl

Wie unterscheidet sich install -c von cp

Zeichnen Sie zufällig eine bestimmte Anzahl von Linien aus einer Datendatei

Wie unterscheidet sich cp -f von cp --remove-destination?

Zeilen von unten extrahieren, bis Regex übereinstimmt

Wie zeigt man bestimmte Zeilen aus einer Textdatei in Linux an?