如何使用 grep 查找任意单词出现 3 次的行?

如何使用 grep 查找任意单词出现 3 次的行?

我想找到包含任意单词三次的行。为此,我认为最好使用该grep命令。

这是我的尝试。

grep '\(.*\)\{3\}' myfile.txt

答案1

使用标准词定义,

  • GNU 格雷普,3个或更多的出现次数任何单词

    grep -E '(\W|^)(\w+)\W(.*\<\2\>){2}' file
    

  • GNU 格雷普,只有3个的出现次数任何单词

    grep -E '(\W|^)(\w+)\W(.*\<\2\>){2}' file | grep -Ev '(\W|^)(\w+)\W(.*\<\2\>){3}'
    

  • POSIX awk,只有3个的出现任何单词

    awk -F '[^_[:alnum:]]+' '{           # Field separator is non-word sequences
        split("", cnt)                   # Delete array cnt
        for (i=1; i<=NF; i++) cnt[$i]++  # Count number of occurrences of each word
        for (i in cnt) {
            if (cnt[i]==3) {             # If a word appears exactly 3 times
                print                    # Print the line
                break
            }
        }
    }' file
    

    为了3个或更多发生时,只需更改==>=.

    等效高尔夫球单线:

    awk -F '[^_[:alnum:]]+' '{split("",c);for(i=1;i<=NF;i++)c[$i]++;for(i in c)if(c[i]==3){print;next;}}' file
    

  • GNU Awk,仅出现 3 次单词ab

    gawk 'gsub(/\<ab\>/,"&")==3' file
    

    为了3个或更多发生时,只需更改==>=.


阅读材料

答案2

像这样?

egrep '(\<.+\>).+\<\1\>.+\<\1\>'
  • egrep(或grep -E)启用扩展正则表达式,这是反向引用所必需的
  • \<.+\>将匹配至少 1 个字符的任何单词
    • \<resp\>匹配单词边界(在您的尝试中,您根本没有考虑单词边界)
    • .+匹配一个或多个字符的序列(在您的尝试中,您使用了.*匹配一系列或更多字符!)
  • 使用反向引用,检查匹配的序列是否出现第二次(\1)和第三次(\1再次)。
    • 我们允许匹配之间存在一个或多个字符 ( ) 的任意序列.+,因此“foo bar foo dorbs foo godly”将匹配(单词“foo”出现 3 次)。
    • 如果您只想匹配相邻的单词(例如“foo foo foo”),请使用类似的内容[[:space:]]+

答案3

我假设你的问题意味着如果该行中的任何单词至少存在 3 次,则打印该行,否则丢弃它。我会使用awk, 来获得更具可读性和可定制性的解决方案:

awk -F '\\W+' '{
    delete c; for (i=1;i<=NF;i++) if (length($i) && ++c[$i]==3) {print; next}
}' file

这是所有字段的循环,计算它们每行出现的次数。如果任何单词达到 3 次,它将打印该行,删除数组并转到下一行。此外,还存在对字段长度的测试,以避免在计数的任何空字段上进行打印。

-F在这里,我们可以通过添加不同和/或许多字段分隔符(支持标准 BRE 和 ERE)来轻松自定义“单词”的含义。上面的单词分隔符都是除_[:alnum:]:awk -F '\\W+'或 之外的所有字符awk -F '[^_[:alnum:]]+',类似于用 匹配单词边界grep

对于人类语言,我们可能需要不同的单词边界,就像除了字母之外的所有内容一样,例如:awk -F '[^[:alpha:]]+'或除了字母和数字:awk -F '[^[:alnum:]]+'或者不仅包含下划线,还包含破折号到单词中:awk -F '[^-_[:alnum:]]+'

如果不设置-F,则仅使用空白字符。

答案4


  • GNU sed在扩展正则表达式模式下-E检测任意单词在一行中恰好重复 3 次的行。

$ r1='.*\<\1\>'
$ r2=$r1$r1 r3=$r2$r1
$ sed -Ee "
    /\<(\w+)\>$r2/! d
    /\<(\w+)\>$r3/d
" file

  • Perl 使用散列将单词存储为键,并将当前行中的计数存储为值。
$ perl -lne 'my %h;
    $h{$_}++ for /\w+/g;
    print if grep { $_ == 3 } values %h;
' file

相关内容