3

I have this file on Linux:

 14:00:01.071 5255  604177
4 14:00:01.074 4608  1415742
 14:00:01.074 18398  1122001
2 14:00:01.074 11723  155575
5 14:00:01.075 4695  885808

Desired Output:

 14:00:01.071 5255  604177
 14:00:01.074 4608  1415742
 14:00:01.074 18398 1122001
 14:00:01.074 11723 155575
 14:00:01.075 4695  885808

Command Used:

gawk '{ print $NF-1, $NF}' filename

But it prints only the last two columns.

  • 9
    Oh, come on. 1) that script does not print the last 2 columns (you're missing parens around NF-1) and 2) assuming you do have a script to print the last column with NF and the 2nd-last column with NF-1, I struggle to believe you couldn't figure out how to build on that pattern to also print the 3rd-last column. – Ed Morton Aug 7 at 15:28
4
$ awk '{ print $(NF-2), $(NF-1), $NF}' file1
14:00:01.071 5255 604177
14:00:01.074 4608 1415742
14:00:01.074 18398 1122001
14:00:01.074 11723 155575
14:00:01.075 4695 885808
7

Assuming

  1. The delimiter is a space
  2. You want all but the first column, which may be blank, but will have a delimiter
  3. There's only one delimiter between columns

then you can use cut -d' ' -f2- to print, from a space-separated values file, the contents from the second column to the last one.

  • I'd suggest adding ...| column -t to have the output properly aligned. – markgraf Aug 9 at 6:43
6

It is quite incorrect, $NF-1 would print the value of the last column subtracted by one. You need to group the command within (..), since NF is a variable

gawk 'NF>=3{ print $(NF-2), $(NF-1), $NF}' file

The part NF>=3 is to safely validate you are printing the last 3 fields on lines that is guaranteed to have at least 3 fields.

3

With GNU grep, you can do:

grep -Eo '\S+\s+\S+\s+\S+\s*$'

Which would preserve the spacing in the input. Note that lines that contain fewer than 3 fields are skipped.

POSIXly, the equivalent would be:

S='[^[:space:]]\{1,\}' s='[[:space:]]\{1,\}'
sed -n "s/$S$s$S$s${S}[[:space:]]*$/\\
&/;s/.*\n//p"
2

I tested with below command and it worked fine

 sed "s/^[0-9]\{1,\}//g" filename| sed -r "s/^\s+//g"

output

14:00:01.071 5255  604177
14:00:01.074 4608  1415742
14:00:01.074 18398  1122001
14:00:01.074 11723  155575
14:00:01.075 4695  885808
  • 2
    It should be noted that this command removes digits in the first column as opposed to printing only the last 3 columns. It's thus hard-coded to expect a certain number of columns as input. – Jeff Schaller Aug 7 at 15:26
  • 2
    It's also unnecessarily GNU-specific for -r and \s, using 2 seds and a pipe when 1 could do the same thing, and using double quotes instead of single unnecessarily. – Ed Morton Aug 7 at 21:41
0

awk '{print $(NF-2),$(NF-1),$(NF)}' file.txt

Where NF is the number of fields in your file.

0

Since the question is tagged perl

$ perl -lane 'print "@F[-3..-1]"' ip.txt
14:00:01.071 5255 604177
14:00:01.074 4608 1415742
14:00:01.074 18398 1122001
14:00:01.074 11723 155575
14:00:01.075 4695 885808
  • -l strip newlines from input lines, and add it to end of string when print is used
  • -a autosplit input based on whitespaces, accessible via @F array
  • print "@F[-3..-1]" print the desired fields, the default delimiter when array is specified within double quotes is single space
    • -1 refers to last field, -2 refers to second last field, etc
    • .. is range operator

Use perl -lane 'print "@F[-3..-1]" if $#F > 2' if you do not want lines with less than 3 fields to be displayed. $#F gives the last index of array, i.e. size of array minus 1

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.