如何使用 awk 打印特定数字后面的所有列?

在 shell 上,当我需要某个特定列时,我通过管道来 awk。

这将打印第9列,例如:

... | awk '{print $9}'

我如何告诉 awk 打印所有的列 包括第9栏及其后,而不只是列9?

111978 次浏览
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'

Generally perl replaces awk/sed/grep et. al., and is much more portable (as well as just being a better penknife).

perl -lane 'print "@F[8..$#F]"'

Timtowtdi applies of course.

When you want to do a range of fields, awk doesn't really have a straight forward way to do this. I would recommend cut instead:

cut -d' ' -f 9- ./infile

Edit

Added space field delimiter due to default being a tab. Thanks to Glenn for pointing this out

ruby -lane 'print $F[3..-1].join(" ")' file
awk '{print substr($0, index($0,$9))}'

Edit: Note, this doesn't work if any field before the ninth contains the same value as the ninth.

awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

This chops what is before the given field nr., N, and prints all the rest of the line, including field nr.N and maintaining the original spacing (it does not reformat). It doesn't mater if the string of the field appears also somewhere else in the line, which is the problem with Ascherer's answer.

Define a function:

fromField () {
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

And use it like this:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost

Output maintains everything, including trailing spaces For N=0 it returns the whole line, as is, and for n>NF the empty string

To display the first 3 fields and print the remaining fields you can use:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

where $1 $2 $3 are the first 3 fields.

sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

Instead of dealing with variable width whitespace, replace all whitespace as single space. Then use simple cut with the fields of interest.

It doesn't use awk so isn't germane but seemed appropriate given the other answers/comments.

Here is an example of ls -l output:

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

My solution to print anything post $9 is awk '{print substr($0, 61, 50)}'

function print_fields(field_num1, field_num2){
input_line = $0


j = 1;
for (i=field_num1; i <= field_num2; i++){
$(j++) = $(i);


}
NF = field_num2 - field_num1 + 1;
print $0


$0 = input_line
}

Using cut instead of awk and overcoming issues with figuring out which column to start at by using the -c character cut command.

Here I am saying, give me all but the first 49 characters of the output.

 ls -l /some/path/*/* | cut -c 50-

The /*/*/ at the end of the ls command is saying show me what is in subdirectories too.

You can also pull out certain ranges of characters ala (from the cut man page). E.g., show the names and login times of the currently logged in users:

       who | cut -c 1-16,26-38

Usually it is desired to pass the remaining columns unmodified. That is, without collapsing contiguous white space.

Imagine the case of processing the output of ls -l or ps faux (not recommended, just giving examples where the last column may contain sequences of whitespace)). We'd want any contiguous white space in the remaning columns preserved so that a file named my file.txt doesn't become my file.txt.

Preserving white space for the remainder of the line is surprisingly difficult using awk. The accepted awk-based answer does not, even with the suggested refinements.

sed or perl are better suited to this task.

sed

echo '1 2 3 4 5 6 7 8 9   10' | sed -E 's/^([^ \t]*[ \t]*){8}//'

Result:

9   10

The -E option enables modern ERE regex syntax. This saves me the trouble of backslash escaping the parentheses and braces.

The {8} is a quantifier indicating to match the previous item exactly 8 times.

The sed s command replaces 8 occurrences of white space delimited words by an empty string. The remainder of the line is left intact.

perl

Perl regex supports the \h escape for horizontal whitespace.

echo '1 2 3 4 5 6 7 8 9   10' | perl -pe 's/^(\H*\h*){8}//'

Result:

9   10