Home > front end >  Reading 3 consecutive lines with awk? (Or something else)
Reading 3 consecutive lines with awk? (Or something else)

Time:07-12

I have a huge file, and at some point it goes like this:

Bla bla bla
LAST ITERATION:        1780           6          12  0.689655172413793
  -8708.81862246834       -8698.33572943212       -2003.09638506407
 -9.912281246897692E-003
Bla bla bla

I would like to get all the numbers after "LAST ITERATION:" and put it in a line in a file. I have managed to get the two first lines with this:

awk 'a && NR==n{ print a,b,c,d,$1,$3 } /LAST ITERATION:/{ a=$3; b=$4; c=$5; d=$6; n=NR 1 }' ./$FOLDER/$NAMEDATA >> $NAMEOUTPUT

But I can't seem to find a way to get the last number which is on the 3rd line. Could anyone help me?

Thanks!

CodePudding user response:

If you are using gawk, where RS can be more than one character, an easier approach would be to use "LAST ITERATION:" as the record separator, and print the first 8 fields of the second record, with a space as the output record seperator:

gawk 'BEGIN{RS="LAST ITERATION:";ORS=" "}NR==2{for(n=1;n<=8;  n)print$n}'

Demo: https://ideone.com/UzwkdN

CodePudding user response:

You might use getline Variable to access future lines, I would use GNU AWK for this task following way, let file.txt content be

Bla bla bla
LAST ITERATION:        1780           6          12  0.689655172413793
  -8708.81862246834       -8698.33572943212       -2003.09638506407
 -9.912281246897692E-003
Bla bla bla

then

awk '/LAST ITERATION/{getline x1;getline x2;line=$0 " " x1 " " x2;sub(/LAST ITERATION:[[:space:]] /,"",line);gsub(/[[:space:]] /," ",line);print line}' file.txt

gives output

1780 6 12 0.689655172413793 -8708.81862246834 -8698.33572943212 -2003.09638506407 -9.912281246897692E-003

Explanation: when LAST ITERATION is encountered I save next line to variable x1 and next next line to variable x2, then construct line from space-sheared current line, next line and next next line, then remove LAST ITERATION: and following whitespaces characters using sub function and alter multiple whitespace characters to single spaces using gsub, after doing that I print said line. Disclaimer: this solution assumes there are always at least 2 lines after line with LAST ITERATION.

(tested in gawk 4.2.1)

CodePudding user response:

If you are using regular awk, you can concatenate the 3 lines starting with the line with LAST ITERATION: to a variable, and split it in the end:

awk 'BEGIN{ORS=" "}/LAST ITERATION:/{n=NR 3}NR<n{s=s$0}END{split(s,a);for(i=3;i<11;  i)print(a[i])}'

CodePudding user response:

If I read your question correctly, you say you want to see an entry within a file, followed by two following lines.
Next to that, you seem to want to work with awk.

My answer is: "Why awk? This can very easily be done using grep.", as follows:

grep has three switches to add more lines, next to the matching one:

  • -A n : add "n" lines after the match
  • -B n : add "n" lines before the match
  • -C n : add "n" lines, combined after and before

So, you can simply use grep -A 2 "match" filename.

Good luck

CodePudding user response:

For batch you can target lines using findstr:

The below can target single lines, consecutive lines or a list of lines.

@Echo off

REM :: CALL %0 <filepath> <integer|integer list>

    Set "File.Name="

    If exist "%~f1" (
        Set "File.Name=%~f1"
    )Else (
        1>&2 Echo(File Not Found
        Exit /B 1
    )
    
    If "%~2" == "" (
        1>&2 Echo(Missing Arg/s for target Line/s.
        Exit /B 2
    )

    Set Target.Lines=%*
    Set "Target.Lines=%Target.Lines:"=%"

    For /f "Delims=" %%G in ('CMD /V:ON /C "Echo(!Target.Lines:%~1 =!"')Do Set "Target.Lines=%%G"

    Set "Line.Count=0"
    Set "Highest.Target=0"
        Setlocal EnableExtensions EnableDelayedExpansion
            For %%G in (%Target.Lines%)Do if !Highest.Target! LSS %%G Set "Highest.Target=%%G"
        Endlocal & Set "Highest.Target=%Highest.Target%"

    For /f "Tokens=1* Delims=:" %%G in ('%SystemRoot%\System32\findstr.exe /VNLC:"{false.string[%~n0]}" "%File.Name%"')Do (
        Set "Line.Count=%%G"
        For %%i in (%Target.Lines%)Do if %%G EQU %%i Echo(%%H
    )

    If %Line.Count% LSS %Highest.Target% (
        1>&2 Echo(Lines missing. Lines in file: %Line.Count%. Highest Target: %Highest.Target%
    )

CodePudding user response:

  awk '
     gsub(/LAST ITERATION:/,""){
        gsub(/^ */,""); 
        o=sprintf("%s ",$0); 
        while(getline && $1 ~ /^[-]?[0-9] (\.[0-9]*)?/) {
           o=o sprintf("%s ", $0)
        } 
        print gensub(/  */," ", "g", o) > "output_file"
    }
  ' input_file 

$ cat output_file
1780 6 12 0.689655172413793 -8708.81862246834 -8698.33572943212 -2003.09638506407 -9.912281246897692E-003
  • Related