简体   繁体   中英

Get variable from 4th line in a while read loop bash

Got a txt file with this scheme: (just 8 of 10k lines)

Paris: 405
Paris_average: 20
Paris_lenght: 30
score: 5.4
London: 605
London_average: 30
London_lenght: 30
score: 6.3

What i need to do is to get the "score" a variable , which is always at the 4th line, and where its value is bigger than "6.0", the 3 lines above needs to be conserved.

So, giving the sample as input, when the script will run, here's the output:

London: 605
London_average: 30
London_lenght: 30
score: 6.3

I've thought about a "while..read" loop for the 4 lines, but I don't know how to go forward. Tagged bash, but also perl solutions are appreciated.

Short awk solution:

awk '$1=="score:" && $2 > 6{ print r1 r2 r3 $0 }{ r1=r2; r2=r3; r3=$0 ORS }' file
  • $1=="score:" && $2 > 6 - check main conditions; $1 and $2 are the 1st and 2nd fields respectively
  • r1=r2; r2=r3; r3=$0 ORS r1=r2; r2=r3; r3=$0 ORS - consecutively reassign each of 3 consequent records into variables r3 -> r2 -> r1
  • print r1 r2 r3 $0 - print a relevant score line along with previous 3 records

Sample output:

London: 605
London_average: 30
London_lenght: 30
score: 6.3

Bonus grep solution:

grep -B3 '^score: [6-9]' file

In case if pattern score: line goes as 2nd line withing 4-lined section/block:

grep -B1 -A2 '^score: [6-9]' file

Following awk may help you on same:

awk '{a[FNR]=$0;} /score:/ && $2>6 && FNR!=1{print a[FNR-3] RS a[FNR-2] RS a[FNR-1] RS $0}'   Input_file

Adding non one liner form of same too now:

awk '
{
  a[FNR]=$0
}
/score:/ && $2>6 && FNR!=1{
  print a[FNR-3] RS a[FNR-2] RS a[FNR-1] RS $0
}
'   Input_file

Explanation:

awk '
{
  a[FNR]=$0                                    ##Creating an array named a whose index is FNR(current line) and value is assigned as current line to it.
}
/score:/ && $2>6 && FNR!=1{                    ##Checking condition here where checking if a line is having string score: in it and 2nd field is greater than 6 and line number is NOT one then do following:
  print a[FNR-3] RS a[FNR-2] RS a[FNR-1] RS $0 ##Printing the value of a[FNR-3](3rd line from current line), RS(record seprator) a[FNR-2](2nd line from current line) a[FNR-1](prevoius line of current line)
}
'   Input_file                                 ##Mentioning Input_file name here too.

Using GNU awk and expecting the score to be of form [0.9].[0-9] and less than 10.0:

$ gawk 'BEGIN{RS="\nscore: ...\n"}RT~/[6789]\./{printf "%s%s",$0,RT}' file
London: 605
London_average: 30
London_lenght: 30
score: 6.3

Explained:

$ gawk '
BEGIN {
    RS="\nscore: ...\n"   # record separator is the score line
}
RT~/[6789]\./ {           # if the score starts with a digit 6-9
    printf "%s%s",$0,RT   # output the record
}' file

Another for reqular awk(s) using buffering and printing:

$ awk '{b=b $0 (NR%4?ORS:"")}!(NR%4){if($2>6)print b;b=""}'  file
London: 605
London_average: 30
London_lenght: 30
score: 6.3

Explained:

$ awk '
{
    b=b $0 (NR%4?ORS:"")  # buffer records
}
!(NR%4) {                 # on every 4th record
    if($2>6)              # if condition met
        print b           # print buffer
    b=""                  # reset buffer
}'  file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM