使用 awk 或 sed 删除多列

使用 awk 或 sed 删除多列

我有一个数据库,其中有 6037 个以空格分隔的列和 450 行,如下所示:

1807 1452 1598 1 6.655713  A B A B ... 0 
1808 1452 1763 1 9.362033  0 0 A B ... A 
1809 1452 1527 2 6.728534  A B A A ... B 
1810 1452 1367 2 9.4055  A B A A B ... A 
... ... ... ... ... ... ... ... ... ...
1812 1452 1258 1 6.363032  0 0 A B ... B

我想要获得一个仅包含前 676 列的新数据库。

最好是使用某种形式awksed命令。

答案1

如果文件中的列分隔符是单个字符(例如空格),cut则可以轻松做到这一点:

cut -d' ' -f-676 <in >out

这将仅打印从第一列到第 676 列以空格分隔的列。

如果您需要将每个空格字符都算作分隔符,则sed解决方案是:

sed -r 's/\s+\S+//677g' <in >out

这将从第 677 列开始的每一列(= 至少一个空格字符,后面跟着至少一个非空格字符)都替换为空。使用字符组,您可以指定所需的任何分隔符集,例如“4”、“#”和“K”:

sed -r 's/[4#K]+[^4#K]+//677g' <in >out

为一个合理的 awk方法请参考steeldriver 的回答但是这里还有另一个循环遍历列并仅FS当它们的数量<= 676时才打印它们(用分隔):

awk '{for (i=1;i<=676;i++) {printf (i==1?"":FS)$i}; print ""}' <in >out

对于字符组,您必须指定输出的输出字段分隔符,例如[4#K]"sep"

awk -F'[4#K]' '{for (i=1;i<=676;i++) {printf (i==1?"":"sep")$i}; print ""}' <in >out

答案2

对于单字符分隔符(例如空格或逗号),我建议使用命令cut而不是awksed

不过既然你awk具体问到了,我思考一个合理的方法是减少字段数量:

awk -v last=676 '{NF = last} 1' datafile

在 GNU Awk ( gawk) 中测试过,并且mawk

答案3

你可以使用

mlr --nidx --fs ' ' --repifs cat inputFile.csv | cut -d ' ' -f-2

以这种方式磨坊主/mlr您管理字段分隔符(如果您有多个空格,则每个字段一个空格),并且使用 cut 您提取(在我的例子中)前两个字段。

1807   1452 1598  1 6.655713  A B A B
1808 1452 1763 1  9.362033  0 0 A B
1809 1452 1527 2 6.728534  A B   A A
1810 1452 1367 2 9.4055  A B A A B

1807 1452
1808 1452
1809 1452
1810 1452

关于 Miller 期权的一些注释:

  • --nidx是设置格式;这是一个通用的索引编号表(第一个字段是 1,第二个字段是 2,等等);
  • --fs设置分隔符(这里是一个空格);
  • --repifs表示字段分隔符连续多次出现算作一个
  • cat将输入记录直接传递到输出。

相关内容