真正的列删除,而不是选择所有想要的列

真正的列删除,而不是选择所有想要的列

我知道这是一个简单的问题,并且之前已经在很多方面得到了解答,但是我见过的 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'

$,=" "将输出字段分隔符设置为单个空格。

笔记:

  1. perl 数组从 0 开始,而不是 1。@F[4]第五列也是如此。

  2. 这将删除第 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)

相关内容