2

Hello I have a text file containing the following info:

#[Tue Oct 25 00:00:02 2016] --- START OUTPUT
#CMD: XXX
END-->0<--
#[Tue Oct 25 00:00:57 2016] --- END
#RETURN: 1
#ELAPSED TIME (in seconds): 55

#[Tue Oct 25 00:05:01 2016] --- START OUTPUT
#CMD: XXX
END-->0<--
#[Tue Oct 25 00:05:33 2016] --- END
#RETURN: 0
#ELAPSED TIME (in seconds): 32

I want to get the --End line the Return line and the Elapsed line if its corresponding Return is > 0.

So far I have just been able to grep the Return line grep "#RETURN:" -A 1 -B 1 f.log

But how to i grep only if the Return is > 0 ?

Desired output:

#[Tue Oct 25 00:00:57 2016] --- END
#RETURN: 1
#ELAPSED TIME (in seconds): 55
4
  • Whats your desired output from this?
    – heemayl
    Commented Oct 25, 2016 at 7:47
  • @heemayl Please check update Commented Oct 25, 2016 at 7:49
  • So your input file has sections separated by empty lines? Commented Oct 25, 2016 at 7:52
  • @SatoKatsura not necessarily. Some are and some are not. Commented Oct 25, 2016 at 7:55

3 Answers 3

5

With awk:

awk '/END$/ {prev=$0; next}; /^#RETURN/ && $2>0 {cur=$0; pr=1; next};\
                      pr {printf "%s\n%s\n%s\n", prev, cur, $0; pr=0}' file.txt
  • /END$/ {prev=$0; next}: If the line ends with END, save it as variable prev, and go to the next line; This is the line before RETURN

  • /^#RETURN/ && $2>0 {cur=$0; pr=1; next}: If the line starts with #RETURN and the second field is greater than 0, then save the line as cur, set variable pr as 1 (true), and go to the next line

  • pr {printf "%s\n%s\n%s\n", prev, cur, $0; pr=0}: If pr is true, then print the output in desired format, and finally set pr as 0 (false)

Example:

% cat file.txt                                                                                                                   
#[Tue Oct 25 00:00:02 2016] --- START OUTPUT
#CMD: XXX
END-->0<--
#[Tue Oct 25 00:00:57 2016] --- END
#RETURN: 1
#ELAPSED TIME (in seconds): 55

#[Tue Oct 25 00:05:01 2016] --- START OUTPUT
#CMD: XXX
END-->0<--
#[Tue Oct 25 00:05:33 2016] --- END
#RETURN: 0
#ELAPSED TIME (in seconds): 32

% awk '/END$/ {prev=$0; next}; /^#RETURN/ && $2>0 {cur=$0; pr=1; next}; pr {printf "%s\n%s\n%s\n", prev, cur, $0; pr=0}' file.txt
#[Tue Oct 25 00:00:57 2016] --- END
#RETURN: 1
#ELAPSED TIME (in seconds): 55
3
  • It's a nice algorithm and I love awk but isn't it a job more suited for grep since the lines are contiguous ? Commented Oct 25, 2016 at 8:04
  • @ValentinB. If the file contents are literal, then yes. Although your approach can be made more compact: 1) egrep is not needed as there is no ERE token in your pattern 2) Use -C1 instead of mentioning both -A and -B as the lien counts are the same. Just do: grep -C1 'RETURN: [1-9][0-9]*' file.txt
    – heemayl
    Commented Oct 25, 2016 at 8:07
  • Well thank you for the input, I will edit my post accordingly! Had not thought that this was not an extended regex, and had forgotten about the context option of grep. Yours is indeed more robust but I will leave mine as a "simple" alternative. Commented Oct 25, 2016 at 8:13
0

you can try this;

awk -F: '/#RETURN:/ && $2 > 0 { getline; print $0}' test

Eg;

user@host:/tmp$ awk -F: '/#RETURN:/ && $2 > 0 { getline; print $0}' test
#ELAPSED TIME (in seconds): 55
0

You should use regular expressions in your grep:

 grep -C1 'RETURN: [1-9][0-9]*' input.txt

That regexp should catch any (positive) number that is not a single 0 (or does not start with a 0).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .