我知道这是一个简单的问题,并且之前已经在很多方面得到了解答,但是我见过的 awk、sed、grep 等的每次使用都是选择并打印您想要的列。如果您想要的列数量未知,而您不想要特定的列,如何删除您不想要的列?
您是否只需选择您不想要的列之前的列,然后选择您不想要的列之后的 n 列?不是有一个简单的删除第n列的函数吗?
我没有例子,因为这更多是出于好奇,但如果有必要我可以举一个。
答案1
好的,你可以使用 cut 命令,但它仍然不是删除所述列,而是选择你想要的列,它确实有一个无限列选项。因此,如果您想选择第 2 列,然后选择第 4 列以后的每一列,则一个解决方案是:
cut -f 2,4- file.txt
不过我仍然有兴趣知道是否有实际的删除命令?
答案2
虽然awk
没有实际从行中删除字段的函数,但您可以将特定列设置为空字符串。
然而,有一个常见的技巧可用于删除列(例如第 5 列和第 7 列):
awk '{$5=$7="" ; $0=$0;$1=$1}1'
将$0=$0;$1=1
$0 设置为自身,将 $1 设置为自身。这样做的副作用是删除任何额外的字段分隔符(即在现在为空的字段 $5 和 $7 之后立即存在的分隔符)
注意:这还会将 $0 中的所有字段分隔符转换为当前设置的输出字段分隔符 (OFS)(例如,使用默认 FS 和 OFS,它将转换为多个制表符和空格字段之间到单身的空间)
和perl
,就容易多了。它做有一个函数 ( splice()
) 从数组中删除列:
perl -lane 'BEGIN{$,=" "}; splice(@F,4,1); splice(@F,5,1); print @F'
$,=" "
将输出字段分隔符设置为单个空格。
笔记:
perl 数组从 0 开始,而不是 1。
@F[4]
第五列也是如此。这将删除第 5 列,因此我们要删除的第二列(第 7 列)现在是第 6 列,这就是第二列
splice
删除 的原因@F[5]
。
为了避免此处出现任何潜在的混淆,请按相反顺序删除列:
perl -lane 'BEGIN{$,=" "}; splice(@F,6,1); splice(@F,4,1); print @F'
或者你可以使用循环:
perl -lane 'BEGIN{$,=" "}; foreach $c (7,5) {splice(@F,$c-1,1)}; print @F'
顺便说一句,如果您只想删除第一的或者最后的列,您可以使用shift @F
、 或pop @F
。
输出:
具有以下输入:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
a b c d e f h i j k
全部上述脚本将产生以下输出:
1 2 3 4 6 8 9 10
10 9 8 7 5 3 2 1
a b c d f i j k
答案3
这取决于您所说的列的含义。如果您实际上指的是字符列而不是分隔字段,那么晦涩难懂的科尔姆允许指定起始列,或指定要删除的一系列列的起始列和结束列。无法在一次调用中删除任意数量的非连续列
答案4
我相信 cut 命令也许对你有用?
在之前的回答中发现了这一点:https://stackoverflow.com/questions/13690461/using-cut-command-to-remove-multiple-columns
关于 cut 命令的更多信息: http://www.computerhope.com/unix/ucut.htm https://en.wikipedia.org/wiki/Cut_(Unix)