【问题标题】:grep or awk - how to return line if column 1 and 3 have the same valuegrep 或 awk - 如果第 1 列和第 3 列具有相同的值,如何返回行
【发布时间】:2013-09-20 02:02:55
【问题描述】:

我有一个制表符分隔的文件,如果第 1 列中的值与第 3 列中的值相同,我希望输出在我的文件中包含整行。对 perl 和 linux 的了解非常有限,这很接近当我找到解决方案时。

文件示例

Apple   Sugar   Apple    
Apple   Butter  Orange   
Raisins Flour   Orange   
Orange Butter  Orange   

结果是:

Apple Sugar Apple   
Orange Butter Orange

代码:

#!/bin/sh  

awk '{    
    prev=$0; f1=$1; f3=$3;    
    getline    
    if ($1 == $3) {    
        print prev    
        print    
    }'    
} myfilename    

我确信有一个更简单的解决方案。甚至可能是命令行上的 grep 或 awk。但那是我能找到的唯一似乎给我解决方案的代码。

谢谢!

【问题讨论】:

    标签: perl awk grep


    【解决方案1】:

    awk 很容易:

    awk '$1 == $3' myfile
    

    默认操作是打印记录,所以如果字段 1 和 3 相等,就会发生这种情况。

    【讨论】:

    • Perl 中相同:perl -lane'print if $F[0] eq $F[2]' myfile
    • +1 因为这是正确的解决方案(一旦您将-F'\t' 添加到它)。 @user2795815 不要使用任何 grep 解决方案,因为它们对于某些输入值会神秘地失败。例如,使用 2 行输入文件尝试它们,其中第一行是 a good a,第二行是 a bad aa(根据您的要求使用制表符分隔)。
    【解决方案2】:

    使用awk

    awk 是工作的工具:

    awk '$1 == $3'
    

    如果您在数据中的字段是严格的制表符分隔并且可能包含空格,那么您将需要明确指定字段分隔符:

    awk -F'\t' '$1 == $3'
    

    (其中\t 表示选项卡;您可能必须键入 Tab(甚至是 Control-VTab)才能将其放入字符串中)。

    使用grep

    你可以用grep做,但你不想用grep做:

    grep -E '([A-Za-z]+)\t[A-Za-z]+\t\1'
    

    正则表达式的关键部分是\1,意思是“与第一个捕获的字符串相同的值。

    你甚至可能在bash 中经历这样的回旋:

    grep -E $'([A-Za-z]+)\t[A-Za-z]+\t\\1'
    

    您可以通过注意(假设)字段中没有空格来简化生活:

    grep -E '([A-Za-z]+)[[:space:]]+[A-Za-z]+[[:space:]]+\1'
    

    正如其中一个 cmets 所述,我没有在搜索模式的末尾添加 $;这将是可行的(尽管必须清理数据以包含制表符并删除尾随空格),因此不会拾取“好噪音好坏”。还有其他方法可以做到这一点,您可以使正则表达式变得越来越复杂以处理更多可能的情况。但那些只是强调awk 解决方案更好; awk 自动处理细节。

    【讨论】:

      【解决方案3】:

      使用grep

      grep -P "([^\t]+)\t[^\t]+\t\1" inFile

      【讨论】:

        猜你喜欢
        • 2019-09-12
        • 2015-11-30
        • 2018-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-04
        • 2021-11-25
        相关资源
        最近更新 更多