Home > Net >  How to catch xth pattern1 to pattern2
How to catch xth pattern1 to pattern2

Time:04-26

this is my example to explain my question :

Bug Day 2022-01-13:
Security-Fail 248975
Resolve:
...
Bug Day 2022-01-25:
Security-Fail 225489
Security-Fail 225256
Security-Fail 225236
Resolve:
...
Bug Day 2022-02-02:
Security-Fail 222599
Resolve:

So, I have a big file that contain multiple security vulnerabilities. I want to obtain that :

2022-01-13;248975
2022-01-25;225489,225256,225236
2022-02-02;222599

I though about doing something like

bugDayNb=$(grep "Bug Day" | wc -l)

for i in $bugDayNb; do
    echo "myBugsFile" | grep -A10 -m$i "Bug Day"
done

The problem of this command is, if there are more than 10 Security-Fail, it won't works, and if I put a "-A50" it may take the next Security-Fail of the next Bug Day.

So I would prefer a way to sed or something like that from xth "Bug Day" to xth "Resolve"

Thank you !!

CodePudding user response:

Here's one way to do it:

$ awk '/^Bug Day/{d=$NF; s=""}
       /^Security-Fail/{d = d s $NF; s=","}
       /^Resolve:/{print d}' ip.txt
2022-01-13:248975
2022-01-25:225489,225256,225236
2022-02-02:222599
  • /^Bug Day/{d=$NF; s=""} save the date to variable d if line starts with Bug Day and initialize s to empty string
    • use {d=$NF; sub(/:$/, ";", d); s=""} if you want ; instead of :
  • /^Security-Fail/{d = d s $NF; s=","} when line starts with Security-Fail append the number to d variable and set s so that further appends will be separated by ,
  • /^Resolve:/{print d} print the results when Resolve: is seen

CodePudding user response:

Would you please try an awk solution:

awk '/^Bug Day/ {f=1; line=$0; next}                    # start of block
    f {line=line ORS $0}                                # append the line if "f" is set
    /^Security-Fail/ {g=1}                              # the block contains "Security-Fail"
    /^Resolve/ {if (g) print line; f=g=0; line=""}      # end of block
' input_file

If you prefer a one-liner:

awk '/^Bug Day/{f=1; line=$0; next} f{line=line ORS $0} /^Security-Fail/{g=1} /^Resolve/{if (g) print line; f=g=0; line=""}' input_file

CodePudding user response:

With your shown samples, please try following awk program.

awk '
/Bug Day/{
  sub(/:$/,"",$NF)
  bugVal=$NF
  next
}
/^Security-Fail/{
  secVal=(secVal?secVal ",":"")$NF
  next
}
/^Resolve:/ && bugVal && secVal{
  print bugVal";"secVal
  bugVal=secVal=""
}
'  Input_file

Explanation: Adding detailed explanation for above.

awk '                               ##Starting awk program from here.
/Bug Day/{                          ##Checking condition if line contains Bug day then do following.
  sub(/:$/,"",$NF)                  ##Substituting : at last of $NF in current line.
  bugVal=$NF                        ##Creating bugVal which has $NF value in it.
  next                              ##next will skip all further statements from here.
}
/^Security-Fail/{                   ##Checking if line starts from Security-Fail then do following.
  secVal=(secVal?secVal ",":"")$NF  ##Creating secVal which has $NF value in it and keep adding value to it with delimiter of comma here.
  next                              ##next will skip all further statements from here.
}
/^Resolve:/ && bugVal && secVal{    ##Checking condition if line starts from Resolve: and bugVal is SET and secVal is SET then do following.
  print bugVal";"secVal             ##printing bugVal semi-colon secVal here.
  bugVal=secVal=""                  ##Nullifying bugVal and secVal here.
}
'  Input_file                       ##mentioning Input_file name here. 
  • Related