I have a script that outputs messages to the standard output. Now I need to fetch the 13th line from the beginning, and the second last line from this output.
I was wondering if this could be done via a single command rather than redirecting the output to the file and then reading through it few times to pull my output.
line 1
line 2
...
line 12
line 13
line 14
...
...
line N-1
line N
I need to fetch the output like:
line 13
line N-1
I have separate commands to get my lines.
To fetch the 13th line:
scriptoutput | head -n 13
To fetch the N-1 line:
scriptoutput | tail -n 2 | head -n 1
OR
scriptoutput | sed 'x;$!d'
But being standard output, I am not able to get the output done in one command.
You never know which line is "second to last" when reading a stream until you read the actual last line and the stream ends. The only possible way, is to always buffer the previous line, and when the stream ends, output the line from the buffer.
For example with sed
:
$ seq 20 | sed -n '13p;${x;p};h'
13
19
etc. with similar tools.
seq 20 | awk 'NR==13{print} {last=current; current=$0} END{print last}'
seq 20 | { n=1; while IFS= read -r line; do if ((n++ == 13)); then printf "%s\n" "$line"; fi; previous=$current; current=$line; done && printf "%s\n" "$previous"; }
But you can also just buffer the whole output and count the number of lines and output the second to last line....
# with a file
seq 20 > tempfile ; sed -n "13p;$(( $(wc -l < tempfile) - 1 ))p" file
# with memory
seq 20 | { buf=$(cat); sed -n "13p;$(( $(wc -l <<<"$buf") - 1 ))p" <<<"$buf"; }