如何打印第三列到最后一列?

150

我正在尝试从一个DbgView日志文件中删除前两列(我对它们不感兴趣)。我似乎找不到一个例子,可以从第三列开始打印直到行的末尾。请注意,每行具有可变数量的列。

我试图从一个 DbgView 日志文件中删除前两列(我对它们不感兴趣)。我似乎找不到一个示例,可以从第三列开始打印,一直到行的末尾。请注意,每行的列数是不确定的。

可能是重复的问题:使用awk从第n列打印到最后一列 - Ciro Santilli OurBigBook.com
19个回答

135

...或者更简单的解决方案:cut -f 3- INPUTFILE,只需添加正确的分隔符(-d),就可以得到相同的效果。


10
请注意,这仅在所有列之间的分隔符完全相同时才有效......例如,您不能使用类似于\d+的分隔符来使用cut命令。(至少我不知道能不能用。) - Zach Wily
81
如果问题的标题是awk,那么除了awk以外的答案就不合适。如果人们需要它来编写awk脚本呢?这个答案应该只是一个评论。 - syaz
30
通常我会同意,但是在这个论坛上出现了许多“毫无必要的awk”,我认为有必要展示另一种完成任务的方式。如果有人向您展示了一种更简单、更快捷的方法,您不会感激吗?也许发帖者认为由于其他问题的答案数量“不算错误,但肯定可改进”,因此awk是唯一的解决方案? - Marcin
14
这就是评论的作用。接受最佳的awk答案,并在评论中提供更好的非awk建议。如果人们开始发布没有完全回答问题的答案,那么在搜索时会变得很烦人(在我的情况下)。 - syaz
14
不仅所有列之间的分隔符必须相同,而且各列之间必须恰好有一个分隔符。因此,如果你要处理将输出与分隔符对齐的程序,最好使用 awk。 - sknaumov
显示剩余7条评论

130
awk '{for(i=3;i<=NF;++i)print $i}' 

4
将 "awk '{for(i=3;i<=NF;++i)print $i}'" 更加简洁。 :) - user172818
1
谢谢,lh3。我只是在复制和粘贴gawk手册的内容。 :) - Jonathan Feinberg
33
多行输入时出现错误,每一列在使用print打印输出时会被视为新的一行。 - meso_2600
24
为解决输出被分割的问题,我提出了以下解决方案:awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'(其中printf不会打印换行符,而print ""则会在其他字段被打印后添加换行符)。 - lauhub
2
或者:echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}',其输出结果为:3 4 5 6 7 8 9 10 - x-yuri
显示剩余4条评论

128

29
我有点晚了,但是对于第一个或第二个字段等于第三个字段的记录(例如3 2 3 4 5),这种方法行不通。 - aleph_null
打印内部范围也是可能的:# 从$3(包括)到$6(不包括); echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN{FS=",";OFS=","}{ print substr($0, index($0,$3), length($0)-index($0,$6)-1) }'; # 输出 3,4,5 - splaisan

39

Jonathan Feinberg的答案将每个字段都打印在单独的行上。您可以使用printf重新构建记录以在同一行上输出,但您也可以将字段向左跳一个位置。

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

2
请注意,这仅适用于 Gnu awk,按照 POSIX 标准不允许使用降低 NF 的方法。 - kvantour
2
@kvantour:它在gawk、mawk、MacOS awk(nawk?)中都可以工作。POSIX似乎对于是否可以减少“NF”保持沉默。 - Dennis Williamson
这是 awk 的一个有趣的“黑暗角落”之一。 - kvantour

24
awk '{$1=$2=$3=""}1' file
注意:此方法会在第1、2、3个字段中留下“空白”,但如果您只想查看输出结果,则不会有问题。

在该命令后添加 | sed s/^\ *// | column -t 以去除前导空格并对齐剩余列。 - MSpreij
1
最后的1代表什么意思?我应该用什么关键字搜索 awk - Itachi
@Itachi 请查看 http://www.catonmat.net/blog/awk-one-liners-explained-part-one/ 的示例1。 - kvantour
2
@Nathan,你可以通过 {$1=$2=$3="";$0=$0;$1=$1}1 来解决这个问题。 - kvantour
这对于在中间清除一些不必要的列(同时仍然抓取到结尾)非常有用!感谢@ghostdog74。 - Erich

19

如果你想要在同一行打印出第三列之后的列,你可以使用:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'
例如:
Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

它将打印:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

正如我们所看到的,即使有空格,工资单也会按正确的行显示。


这很好,只是我有一个$NF被排除的问题。当我设置条件(<=NF)时,我得到了最后一个字段,但第一个字段的第一个字符被切掉了。我是否在功能方面有什么误解? - Ken Ingram
看起来我的问题是^M卡在了最后一列的末尾。不知道该如何去除它。 - Ken Ingram

9

以下是需要翻译的内容:

以下这一行指令是干什么用的:

awk '{$1=$2=$3=""; print}' file

这是根据@ghostdog74的建议编写的指令,当你过滤行时,它应该表现得更好,即:

awk '/^exim4-config/ {$1=""; print }' file

1
简短明了。也可以在命令末尾添加 sed 's/\s\+//g' 来删除前导空格。 - jumping_monkey

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

这个函数会截取给定字段号N之前的内容,并输出包括字段号N在内的剩余部分,保持原有间距(不重新格式化)。如果该行中出现了字段的字符串,则不影响函数操作。这是daisaa答案存在的问题。
定义一个函数:
fromField () { 
awk -v m="\x0a" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

并像这样使用:

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

输出内容保留所有字符,包括末尾空格。

适用于换行符为 '/n' 的文件。这样你就不会在行内出现新的换行符。如果你想在其他换行符情况下使用它,请使用:

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

例如。只要文件中不使用行内十六进制字符nr.1,就可以与几乎所有文件很好地配合使用。

7
awk '{a=match($0, $3); print substr($0,a)}'

首先你需要找到第三列开始的位置。通过substr函数,你可以从该位置开始打印整行($0),直到末尾。


5
以下 awk 命令会打印每行的最后 N 个字段,并在行末打印一个新行字符:
awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

在下面的示例中,列出了/usr/bin目录的内容,然后保留最后3行并使用awk打印每行的最后4列:
$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接