Gil*_*les 7 text-processing columns
我知道这是一个简单的问题,并且之前已经在很多方面得到了回答,但是我所看到的 awk、sed、grep 等的每次使用都在选择和打印您想要的列。如果您想要的列数未知,而您不想要的特定列,您如何删除您不想要的列?
您是否只需选择前面的列,然后选择您不想要的列之后的 n 列?不只是一个简单的删除列 n 函数吗?
我没有一个例子,因为它更多是一个好奇的问题,但如果有必要,我可以画一个。
虽然awk
没有实际从行中删除字段的函数,但您可以将特定列设置为空字符串。
然而,有一个常见的技巧可用于删除列(例如第 5 列和第 7 列):
awk '{$5=$7="" ; $0=$0;$1=$1}1'
Run Code Online (Sandbox Code Playgroud)
将$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'
Run Code Online (Sandbox Code Playgroud)
$,=" "
将输出字段分隔符设置为单个空格。
笔记:
perl 数组从 0 开始,而不是 1。@F[4]
第五列也是如此。
这将删除第 5 列,因此我们要删除的第二列(第 7 列)现在是第 6 列,这就是第二splice
列删除的原因@F[5]
。
为了避免此处出现任何潜在的混淆,请按相反顺序删除列:
perl -lane 'BEGIN{$,=" "}; splice(@F,6,1); splice(@F,4,1); print @F'
Run Code Online (Sandbox Code Playgroud)
或者你可以使用循环:
perl -lane 'BEGIN{$,=" "}; foreach $c (7,5) {splice(@F,$c-1,1)}; print @F'
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您只想删除第一列或最后一列,可以使用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
Run Code Online (Sandbox Code Playgroud)
上述所有脚本都会产生以下输出:
1 2 3 4 6 8 9 10
10 9 8 7 5 3 2 1
a b c d f i j k
Run Code Online (Sandbox Code Playgroud)