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.