2017-07-22 31 views
1

Ich habe ein Problem, einen bestimmten Wert in einer TXT-Datei mit grep und awk zu extrahieren. zeige ich hier einen Auszug aus der TXT-Datei: „-Wie extrahiere ich einen bestimmten Wert mit grep und awk?

bravais-lattice index  =   2 
lattice parameter (alat) =  10.0000 a.u. 
unit-cell volume   =  250.0000 (a.u.)^3 
number of atoms/cell  =   2 
number of atomic types =   1 
number of electrons  =  28.00 
number of Kohn-Sham states=   18 
kinetic-energy cutoff  =  60.0000 Ry 
charge density cutoff  =  300.0000 Ry 
convergence threshold  =  1.0E-09 
mixing beta    =  0.7000" 

I definiert auch einige Variable: ELEMENT und lat Ich möchte die extrahieren.‚Unit-Zellvolumen‘Wert, der 250.00 gleich . habe ich versucht, die folgenden den Wert mit grep und awk zu extrahieren.

volume=`grep "unit-cell volume" ./latt.10/$ELEMENT.scf.latt_$lat.out | awk '{printf "%15.12f\n",$5}'` 

Allerdings, wenn ich die bash-Datei ausführen ich 00,000000 immer als Ergebnis anstelle des korrekten Wert von 250,00

Kann mir bitte jemand helfen? Vielen Dank im Voraus.

Antwort

3
awk '{printf "%15.12f\n",$5}' 

Sie awk fragst das fünfte Feld der Zeile drucken ($5).

unit-cell volume   =  250.0000 (a.u.)^3 
1   2    3  4  5 

Das fünfte Feld ist (a.u.)^3, die Sie dann awk gefragt werden als Nummer über den %f Formatcode zu interpretieren. Es handelt sich jedoch nicht um eine Zahl (oder beginnt tatsächlich nicht mit einer Zahl), und wenn awk aufgefordert wird, eine nicht numerische Zeichenfolge als Zahl zu behandeln, wird stattdessen 0 verwendet. Somit wird 0 gedruckt.

Lösung: Verwenden Sie stattdessen $4.

Übrigens können Sie den Aufruf von grep überspringen, indem Sie awk selbst verwenden, um die Zeile auszuwählen, z.

awk /^ unit-cell/ {...} 

Die /^ unit-cell/ ist ein regulärer Ausdruck, „unit-cell“ (mit einem führenden Raum) am Anfang der Zeile übereinstimmt. Passen Sie sie gegebenenfalls an, wenn Sie andere Zeilen haben, die mit unit-cell beginnen, die Sie nicht auswählen möchten.

0

Da Sie Schlüssel/Wert-Paare verarbeiten, bei denen der Schlüssel eine variable Menge an Leerzeichen enthalten kann, müssen Sie diese Feldnummer ($ 4, $ 5 usw.) für jeden zu bearbeitenden Datensatz separat einstellen, sofern Sie nicht festlegen Feldtrenner (FS) entsprechend zu FS=" *= *". Dann wird der Schlüssel immer in $ 1 und Wert in $ 2 sein.

Verwenden Sie dann split, um den Wert und die Einheitenteile voneinander zu trennen.

Auch Sie, dass grep durch die Definition in awk verlieren kann ein Muster (oder Bedingung, /unit-cell volume/) für diese print Aktion:

$ awk 'BEGIN{FS=" *= *"} /unit-cell volume/{split($2,a," +");print a[1]}' file 
250.0000 

Erklärt:

$ awk ' 
BEGIN { FS=" *= *" } # set appropriate field separator 
/unit-cell volume/ { # pattern or condition 
    split($2,a," +") # split value part to value and possible unit parts 
    print a[1]   # output value part 
}' file 
1

Sie nie grep benötigen, wenn Sie verwende awk, da awk etwas Nützliches tun kann, was grep tun kann.Es klingt wie das alles ist, was Sie brauchen:

$ awk -F'=' '/unit-cell volume/{printf "%.2f\n",$2}' file 
250.00 

Die oben genannten Arbeiten, weil, wenn FS ist = das bedeutet $2 ist <spaces>250.000 (a.u.)^3 und wenn awk wird aufgefordert, einen String in eine Zahl zu konvertieren es führende Leerzeichen und alles, was nach dem abstreift numerischer Teil, so dass 250.000 in eine Zahl von %.2f umgewandelt werden.

Im Skript Sie $5 geschrieben wurde scheitern, weil der 5. Leerzeichen getrennte Feld in:

$1   $2 $3  $4   $5 
<unit-cell> <volume> <=> <250.0000> <(a.u.)^3> 

ist (a.u.)^3 - man muss nur print $5 hinzugefügt haben könnte, das zu sehen.

Verwandte Themen