GNU/Linux >> Znalost Linux >  >> Linux

Awk z různých řádků?

Snažím se extrahovat nějaká data ze souboru, který se neustále aktualizuje, a přišel jsem na to, jak filtrovat dva řetězce pomocí grep. Výstup je následující:

!    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

Nyní bych chtěl z těchto řádků extrahovat čísla následovně:
z řádku začínajícího na ! Chci číslo ve sloupci č. 5 a od dalšího řádku ve výstupu grep chci číslo ve sloupci č. 6.
Dále bych chtěl tato čísla zapsat do samostatného souboru jako dva oddělené sloupce jako:

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

Myslel jsem, že přístup s awk projde všechny tyto výsledky grep a pak se podívá na liché řádky a vytiskne sloupec 5 a pak na sudé řádky vytiskne sloupec 6. Ale nemám ponětí, jak to udělat.

Zkoušel jsem extrahovat jednotlivé výsledky do proměnných samostatně:

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

a

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

a pak jsem je zkusil zapsat do souboru jako:

echo $var1 $var2 > data.dat

Výsledek však není podle očekávání:

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

Nevím, jak je napsat ve formě, kterou jsem uvedl výše. Vzhledem k tomu, že soubor je neustále aktualizován, představuji si, že část kódu bude zkombinována s podmínkou while loop do a end (tuto poslední část vím)

Doufám, že jsem to vysvětlil jasně!

Přijatá odpověď:

awk řešení:

awk 'v && NR==n{ print $6,v > "result.txt" }/^!/{ v=$5; n=NR+1 }' file
  • <condition1> { <statement> ... }<condition2>{ <statement> ... } – podmínky s příslušnými prohlášeními budou vyhodnoceny postupně

  • /^!/{ v=$5; n=NR+1 } – při zjištění řádku začínajícího ! – zachytit hodnotu 5. pole $5 a naplánujte číslo dalšího řádku NR+1 (přiřazení proměnné n )

  • v && NR==n – máme-li 1. rozhodující číslo v a aktuální číslo záznamu NR je potřebné „číslo dalšího řádku“ n – vytisknout hodnoty do souboru result.txt

Soubor result.txt obsah souboru:

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

Linux
  1. Počítejte řádky, slova a znaky ze souboru v Linuxu

  2. Odstranění konkrétních řádků ze souboru v příkazovém řádku Linuxu

  3. Příkaz wc pro Linux

  1. Vytiskněte poslední řádek souboru z CLI

  2. Odstraňte liché nebo sudé řádky z textového souboru

  3. Výpis řádků pouze z jednoho souboru v DIFF

  1. Odstraňte prvních N řádků z aktivního souboru protokolu

  2. Náhodně nakreslete určitý počet řádků z datového souboru

  3. jak se liší cp -f od cp --remove-destination?