【问题标题】:return whole column of tab separated csv file that has grep match返回具有 grep 匹配的制表符分隔的 csv 文件的整列
【发布时间】:2014-03-13 12:37:06
【问题描述】:

假设我有一个制表符分隔的 csv 文件,如下所示:

a b c  
d e f  
g h i  

使用命令行实用程序,有没有一种方法可以返回与所需 grep 模式匹配的整个列,或者在上面的示例中,我想返回第二列以获取 b 的 grep?

【问题讨论】:

    标签: regex linux csv command-line grep


    【解决方案1】:
     awk -F'\t' -v pat="b" 'NR==FNR{for(i=1;i<=NF;i++)if($i~pat)c[i];next}
                            {s="";for(i=1;i<=NF;i++)
                             if(i in c)s=s sprintf("%s\t", $i);
                             sub(/\t$/,"",s);print s}' file file
    

    这条线完成了这项工作。

    • 它将打印与您的pat 匹配的所有列,并保持column 格式。
    • pat 是正则表达式,您可以将 shell 变量传递给 awk 行
    • 输出遵循原始列顺序

    看看这个例子:(我在你的第 3 列添加了一个b 以显示多个匹配的情况):

    kent$  cat f
    a       b       c
    d       e       b
    g       h       i
    
    kent$  awk -F'\t' -v pat="b" 'NR==FNR{for(i=1;i<=NF;i++)if($i~pat)c[i];next}{s="";for(i=1;i<=NF;i++)if(i in c)s=s sprintf("%s\t", $i);sub(/\t$/,"",s);print s}' f f
    b       c
    e       b
    h       i
    

    【讨论】:

      【解决方案2】:

      如果只有一个匹配,你可以这样做:

      $ awk -v patt="b" 'FNR==NR {for (i=1;i<=NF;i++) $i~patt && col=i; next} {print $col}' file file
      b
      e
      h
      

      说明

      它在文件中循环两次。首先获取匹配文本的列号。其次是打印该特定列。

      • -v patt="b"给模式
      • FNR==NR {for (i=1;i&lt;=NF;i++) $i~patt &amp;&amp; col=i; next} 在第一次读取时,循环遍历字段并检查模式是否匹配。如果是这样,请将列号存储在 col 变量中。
      • {print $col} 打印所有行的特定列。

      【讨论】:

        【解决方案3】:

        您确实需要提示您的文件有多大,您希望多久运行一次,以及您有多少列。但是

        1. grep 快(比 awk 快)
        2. 除非您的文件很大,否则它们很可能会被缓存(因此可以读取两次)

        根据以上观察,我会

        1. grep 模式的文件(如果需要,将结果通过管道传输到 uniq)
        2. 从 grep 的输出中计算需要哪些列
        3. 使用 -vCOLS="c1 c2 c3..." 运行 awk 和打印由 c1、c2... 指定的列的简单脚本

        【讨论】:

        • 我正在使用的文件大小为 1K-2K
        猜你喜欢
        • 2016-12-26
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 1970-01-01
        • 2019-07-30
        • 1970-01-01
        • 2014-07-15
        • 1970-01-01
        相关资源
        最近更新 更多