Poornima Hegde
Poornima Hegde

Reputation: 163

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

I want to retrieve version number from rsense -version command. Output:

 rsense version 0.5.18 
 Usage: rsense <start|stop|restart>

What I tried : If I save the output in one text file say output.txt and execute this command awk 'NR == 1 {print $3}' /Users/poornima/Desktop/output.txt . I am getting required result , i.e. 0.5.18.

But rsense -version | awk 'NR == 1 {print $3}' is not working. Output:

    rsense version 0.5.18
    Usage: rsense <start|stop|restart>

Upvotes: 1

Views: 137

Answers (2)

axiac
axiac

Reputation: 72206

There are several ways to accomplish the same goal using the standard Unix text processing tools.

Using cut

rsense --version | head -n 1 | cut -f3 -d' '

head -n 1 outputs only the first line of its input.
cut -f3 -d' ' outputs the 3rd field of its input using space (' ') as field delimiter (the default delimiter is the tab character).

Using sed

rsense --version | sed -n "1s/^rsense version //p"

There is no need for head -n 1 any more because sed can be instructed what lines of the input to process.
"1s/^rsense version //p" is a sed programs. It tells sed to:

  • 1 - the rest of the command applies only to the first line of the input;
  • s/^rsense version // - search ^rsense version and replace it with the empty string (the replacement string is provided between the second and the third / characters);
    the search string is a regular expression; ^ means the start of the string; the rest of the search string matches exactly the input string; all in all, the search string provided here means "rsense version at the beginning of the line" (please also note the space character after version).
  • p - print the line after the replacement.

-n tells sed to not print its input (this is how it works by default). This suppress any output unless it is specifically required by using a p command (we want to print only the 1st line).

Using bash arrays

a=($(rsense --version | head -n 1))
echo ${a[2]}

By wrapping a command in $(), its output is captured and used instead of the command. After rsense --version | head -n 1 is executed, the first line is the same as a=(rsense version 0.5.18).
The braces around the text creates a bash array. Each work is an entry in the array. The arrays are numerically-indexed, starting with 0. The third word of the text becomes the value at index 2.
${a[2]} is the value stored in the array a at index 2 (the desired version number in this case).

Upvotes: 0

cdarke
cdarke

Reputation: 44354

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.

Upvotes: 2

Related Questions