2

We can print the last column of each line in a file using $NF if we don't know the last column number.

But I facing difficulty is the last column has an empty value.

For example, Parsing who command

$ who
root     tty1         2018-01-25 09:36
root     pts/0        2018-05-30 07:39 (192.168.1.134)
root     pts/1        2018-05-28 23:12 (192.168.1.134)
root     pts/2        2018-06-01 10:01 (192.168.1.188)

Getting result:

$ who | awk '{print $NF}'
09:36
(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

Expected Result


(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

Let me know the possibilities of getting expected result in a one-liner.

EDIT 1: The above scenario is only an example. I don't like to change the delimiter to achieve the result.

EDIT 2: nothing (an empty line of output) from the lines that have fewer fields than the maximum

  • @Archemar who shows only the hostname/IP for non-local logins. – Kusalananda Jun 1 '18 at 7:23
  • Considering the general case: how do you define which field you want? Do you want the last field from the lines that have the most fields, and nothing from the lines that have less fields than the maximum? Or do you have some a priori information about the data? – ilkkachu Jun 1 '18 at 7:38
  • @ikkachu Thanks for the suggestions. I have updated my question. – msp9011 Jun 1 '18 at 7:40
  • Do you want an empty line of output for input lines that have fewer than 5 fields or skip those lines altogether? – Stéphane Chazelas Jun 1 '18 at 9:17
  • @Stéphane Chazelas, AWK - print last column along with empty value. Your answer worked for me with a small change which I did in the comment. – msp9011 Jun 1 '18 at 9:31
5

To only output the last column of rows that have the max number of columns, you could do something like:

who | awk '
  NF > max  {max = NF; output = ""}
  NF == max {output = output $NF ORS}
  END       {printf "%s", output}'

To output one row for every row of input, but empty for rows that don't have the max number of columns:

who | awk '
  NF > max {max = NF}
  {n[NR] = NF}
  NF == max {last[NR] = $NF}
  END {for (i = 1; i <= NR; i++) print n[i] == max ? last[i] : ""}'
  • Works like charm!!! {max = NF; output = "\n"} gave me the result i expects. Thank you. – msp9011 Jun 1 '18 at 8:17
3

If you want the last field only from the lines that have the most fields, you'll need to read through the data twice: once to find out the highest number of fields, and another time to print the fields. Reading just once doesn't cut it: any line could have more fields than the ones before, and there's no way to know.

With awk (note the filename is given twice):

awk -vfields=0 'FNR==NR {if (NF > fields) fields=NF; next} 
     NF >= fields { print $NF } NF < fields {print ""}' file file

If file contains

foo bar
one two three four
1 2 3
a b c d

this prints the fourth field, or empty for lines that don't have it:


four

d

That, of course doesn't work with a pipe, you'll have to use a temporary file.

An alternative solution could cache the to-be-printed fields until a line with more fields appears, as in Stéphane's answer.

1

Check if the 5th field matches \(.*\), and print it if it does.

who | awk '$5 ~ /\(.*\)/{print $5}'

If you are only interested in ip addresses then change the regex:

who |  awk '$5 ~ /\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)/{print $5}'
0

If you only want to get the last column if this column is available, use the fact that lines that you don't want have only four columns:

who | awk 'NF > 4 { print $NF }'

or, to get similar data,

w -hi | awk '{ print $3 }'
  • Thanks for your input, But as I mentioned in the question, How can we achieve without knowing the field number 4. – msp9011 Jun 1 '18 at 7:38
  • @SivaPrasath You do know that who outputs five fields, or four if the user is logged in locally, because you have read the manual for who. – Kusalananda Jun 1 '18 at 7:40
  • as mentioned in the question, who is just an example. I would like to achieve the result without knowing the max field as answered by @Stéphane – msp9011 Jun 1 '18 at 8:25
  • @SivaPrasath I'd still argue that you know what you're parsing, or you would have no clue what data you wanted. If it's the output of a command, you will obviously read its manual to know what kind of output it produces. If it's a data file, then it most likely also follows some sort of pattern. – Kusalananda Jun 1 '18 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.