Get First Line of a Shell Command's Output

Get first line of a shell command's output

Yes, that is one way to get the first line of output from a command.

If the command outputs anything to standard error that you would like to capture in the same manner, you need to redirect the standard error of the command to the standard output stream:

utility 2>&1 | head -n 1

There are many other ways to capture the first line too, including sed 1q (quit after first line), sed -n 1p (only print first line, but read everything), awk 'FNR == 1' (only print first line, but again, read everything) etc.

How to get the first line of a file in a bash script?

head takes the first lines from a file, and the -n parameter can be used to specify how many lines should be extracted:

line=$(head -n 1 filename)

Linux: Extract the first line of a file

Edit: you can't use my old answer (see below) with OpenWrt since OpenWrt doesn't ship with ed. What a shame. So here are two methods:

The vi way

vi is a genuine editor too, so the following will work:

vi -c ':1d' -c ':wq' file > /dev/null

We open the file with vi, and use the commands :1d to delete the first line and :wq to save and quit, redirecting all output to /dev/null. Cool, clean, short and simple.

Oh, you will of course run:

firstline=$(head -n1 file)

before running this vi command to get the first line of the file into the variable firstline.

Note. On a system with very little memory, and when file is huge, this method fails.

The dd way

dd is a cool tool for this. The dd methods given in other answers are really great, yet they rely on the truncate utility which does not ship with OpenWrt. Here's a workaround:

firstline=$(head -n1 file)
linelength=$(head -n1 file | wc -c)
newsize=$(( $(wc -c < file) - $linelength ))
dd if=file of=file bs=1 skip=$linelength conv=notrunc
dd if=/dev/null of=file bs=1 count=0 seek=$newsize

This will work even with huge files and very little memory! The last dd command plays the role of the truncate command given in the other answers.


Old answer was:

You can use ed for this:

firstline=$(printf '%s\n' 1p d wq | ed -s file.txt)

At each call, you'll get the first line of the file file.txt in the variable firstline, and this line is removed from the file.

How to get the value of last word in 1st row from command output

I don't have rsense, but some programs write their version number to stderr, not stdout. Try:

rsense -version 2>&1 | awk 'NR == 1 {print $3}'

The meaning of 2>&1: file streams are allocated numbers known as file descriptors (fds):

0 is stdin, by default the keyboard, redirection symbol < or 0<

1 is stdout, by default the screen, redirection symbol > or 1>

2 is stderr, by default the (unbuffered) screen, redirection symbol 2>.

We can redirect to a file or to another file descriptor, prefixed by & (see man dup2).

So 2>&1 means, redirect file descriptor 2 (stderr) to file descriptor 1 (stdout). This is because pipes | only connect stdout on the left side to the stdin on the right - they don't use stderr (fd 2).

Here is an alternative which uses a bash array instead of the awk language (in theory this should be more efficient since it avoids loading and running an awk external process):

a=($(rsense -version 2>&1))
echo ${a[2]} # arrays count from zero, awk counts from 1

By the way, your question asks for the last word. In bash this would be:

echo ${a[-1]}         # assumes a recent version of bash

in awk would be:

awk '{print $NF}'

In awk, $NF gives the Number of Fields.

How to read only the first line of the output from a file descriptor?

You can capture the first line of an arbitrary file descriptor in this way:

$ (printf '%s\n' foo bar >&3) 3> >(head -n1)
foo

This prints two lines to FD 3 and redirects that to standard input of head. If you want to store that result to a file simply redirect within the process substitution.

Command to get nth line of STDOUT

Using sed, just for variety:

ls -l | sed -n 2p

Using this alternative, which looks more efficient since it stops reading the input when the required line is printed, may generate a SIGPIPE in the feeding process, which may in turn generate an unwanted error message:

ls -l | sed -n -e '2{p;q}'

I've seen that often enough that I usually use the first (which is easier to type, anyway), though ls is not a command that complains when it gets SIGPIPE.

For a range of lines:

ls -l | sed -n 2,4p

For several ranges of lines:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'

getting first column of a matching line in bash

You may use awk like this:

name=$(kubectl get pods -n system | awk '/^my-pod.*Running/{print $1}')
[[ -n $name ]] && kubectl -n system logs "$name" --tail=5 -f

awk command will match pattern my-pod.*Running at the start of a line and if it is found then it will print first column. We store that in variable name.

If $name is not empty then we call kubectl -n system logs using that value.

Omitting the first line from any Linux command output

Pipe it to awk:

awk '{if(NR>1)print}'

or sed

sed -n '1!p'


Related Topics



Leave a reply



Submit