Print all lines between patterns

Hi Gurus,

I have a requirement where I need to display all lines between 2 patterns except the line where the first pattern in it. I tried the following command using awk but it is printing all lines except the lines where the 2 patterns exist.

awk '/TRANSF_/{ P=1; next } /Busy/ {exit} P' sess.log

Input file will be like this.

Thread [TRANSF_1_1_1] created for [the transformation stage] of partition point [SQ_MAIL] has completed.
        Total Run Time = [338.043617] secs
        Total Idle Time = [0.000000] secs
        Busy Percentage = [100.000000]
        Thread work time breakdown:
                EXP_MAIL: 100.000000 percent
Thread [WRITER_1_*_1] created for [the write stage] of partition point [MAIL_OUT] has completed.
        Total Run Time = [278.223948] secs
        Total Idle Time = [278.114421] secs
        Busy Percentage = [0.039367]

I want the output as

TRANSF
        Total Run Time = [338.043617] secs
        Total Idle Time = [0.000000] secs
        Busy Percentage = [100.000000]
WRITER
        Total Run Time = [278.223948] secs
        Total Idle Time = [278.114421] secs
        Busy Percentage = [0.039367]

Thanks,
S

awk -F'[][]' '/^Thread/{gsub(/_.*/,x,$2);print $2;n=0;next}/Busy/{n=1;print;next}!n' file
sed -n '/^Thread \[/ { s///; s/_.*//; N; N; N; p; }'

Regards,
Alister

1 Like
$ sed -n "/^Thread/,/Busy Percentage/ { s/^Thread .//; s/_.*//; p}" input
TRANSF
        Total Run Time = [338.043617] secs
        Total Idle Time = [0.000000] secs
        Busy Percentage = [100.000000]
WRITER
        Total Run Time = [278.223948] secs
        Total Idle Time = [278.114421] secs
        Busy Percentage = [0.039367]
1 Like

Move the P (print if P is not 0) before the /Busy/ {exit}

1 Like

Thank you.

Can you please explain the above command?

Thanks,
S

Explanation:

awk -F'[][]' '                                  # Set [ ] as field separators
        /^Thread/ {                             # Search if record begins with pattern: Thread
                        gsub ( /_.*/, x, $2 )   # Substitute underscore followed by zero or more occurrence of any char in $2 with x (null variable)
                        print $2                # Print $2 (second field)
                        n = 0                   # Set variable n = 0
                        next                    # Skip processing current record
        }

        /Busy/ {                                # Search if record contains pattern: Busy
                        print $0                # Print $0 (whole record)
                        n = 1                   # Set variable n = 1
                        next                    # Skip processing current record
        }

        !n                                      # !n (Print whole record when n = 0, !n == 1 (when true default action is print)
' file

I hope this helps.

1 Like

This is close to what you tried in post #1, and should work

awk '/TRANSF_/{f=1} f {print; if ($0~/Busy/) exit}' sess.log
Thread [TRANSF_1_1_1] created for [the transformation stage] of partition point [SQ_MAIL] has completed.
        Total Run Time = [338.043617] secs
        Total Idle Time = [0.000000] secs
        Busy Percentage = [100.000000]
1 Like

Correction of my previous post: P when moved needs to be followed by {print} :

awk '/TRANSF_/{ P=1; next } P {print} /Busy/ {exit} P' sess.log

Indeed this is pretty close to the previous solution.
A nice optimization is to further shuffle the order:

awk 'P {print} /TRANSF_/ {P=1} /Busy/ {exit}' sess.log

Its ok, if you do not want the TRANSF line.

Here is another one

awk '/TRANSF_/,/Busy/' sess.log