`cut`:选择包含字符串的列

`cut`:选择包含字符串的列

我有一个大文件,每行有几列。我熟悉使用cut -f -d按编号选择特定列。

我检查了手册cut,似乎没有一种方法可以正则表达式匹配列。

我具体想做的是:

  • 选择每行的第二列
  • 并选择包含字符串“hello”的所有列(可能没有,如果没有,则可能是任何列,并且每行的列不同)

进行此操作最方便的终端工具是什么?

编辑:

简化示例

x ID23 a b c hello1
x ID47 hello2 a b c
x ID49 hello3 a b hello4
x ID53 a b c d

我想要的结果是:

ID23 hello1
ID47 hello2
ID49 hello3 hello4

或者:

ID23 hello1
ID47 hello2
ID49 hello3 hello4
ID53

详细说明给出的示例:

  • 列由一个空格定义
  • 是否“仅在字符串存在时打印”并不重要,grep如果需要的话我可以只打印“hello”
  • 我们可以假设字符串“hello”永远不会出现在第 1 列或第 2 列中。

答案1

如果行尾的一个空格不会对您造成太大影响:

$ awk '{for(i=1;i<=NF;i++) if(i==2 || $i~"hello") printf $i" ";print ""}' file

ID23 hello1 
ID47 hello2 
ID49 hello3 hello4 
ID53 

这不会对“hello”字符串的位置进行任何假设。

答案2

我认为使用像cut.或者,至少,不容易。这是一个 Perl 解决方案:

$ perl -lane '$k=join " ",grep{/hello/}@F; print "$F[1] $k" if $k' file 
ID23 hello1
ID47 hello2
ID49 hello3 hello4

您可以首先使用以下方法来简化grep

$ grep hello file | perl -lane 'print "$F[1] ", join(" ", grep{/hello/}@F)'
ID23 hello1
ID47 hello2
ID49 hello3 hello4

解释

-n选项指示perl逐行读取其输入并应用 给出的脚本-e。该标志为每个调用-l添加一个换行符 ( ) 。该选项将空格上的输入行拆分到数组中。\nprint-aperl@F

因此,脚本本身正在查找@F(所有列)匹配的所有元素hello,并将它们保存为空格分隔的字符串$k( $k=join " ",grep{/hello/}@F;)。然后,如果已定义且至少找到一个,则打印第二个字段 ( $F[1]) 和。$k$khello

第二个版本是相同的,只是我们不需要$k直接打印,因为我们知道至少有一个hello总是存在。

相关内容