如何使用 grep 搜索某个单词的出现和另一个单词的缺失

如何使用 grep 搜索某个单词的出现和另一个单词的缺失

我有一个文件,其内容类似于:

google.com,9,AB+CD,nonAB+nonCD
youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

列数不固定。但第一列是 URL,第二列是数字,从第三列开始是用逗号分隔的关键字,但每个网站都不同。

我想计算 URL(行)的数量,以便控制行中的关键字。例如,
1)AB+CD没有nonABand nonCD。注意:AB+CD 这个词可以出现多次。2) AB+CD 没有出现nonCD(但如果有其他内容也可以)

如何在一行中搜索一个字符串并确保不存在另一个字符串。当我使用:

grep 'AB+CD' test.txt > result.txt

它打印出找到“AB+CD”的每一行。

如果我想打印只有“AB+CD”的行,该怎么办:

youtube.com,9,AB+CD,AB+CD

或者将 'AB+CD' 与 'nonAB' 以外的任何其他项组合在一起,得到:

youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

答案1

如果您只是想要进行纯文本搜索而不关心列,则可以grep -v像这样链接反向匹配:

cat input.txt | grep 'IncludedText' | grep -v 'ExcludedText'

如果您想按列进行适当的过滤,您可能需要使用类似的东西awk

答案2

一般技巧:

  1. 包含以下内容的行foo以及包含bar( foo OR bar) 的行:

    grep -e foo -e bar
    
  2. 在同一行中包含foo和 的行( ):barfoo AND bar

    grep foo | grep bar
    
  3. 不包含baz( NOT baz) 的行:

    grep -v baz
    

使用这些积木,您可以构建逻辑。问题-v不仅限于单个模式,而是全局性的grep(至少在我的 Debian 中)。这使得以下操作成为NOT (foo OR bar)可能:

grep -v -e foo -e bar

这相当于(NOT foo) AND (NOT bar)

grep -v foo | grep -v bar

然而NOT (foo AND bar)(逻辑上等同于(NOT foo) OR (NOT bar))并不那么容易。我们可以尝试foo AND bar单身的(扩展)grep

  1. 再次在同一行中包含foo和 的行( ):barfoo AND bar

    grep -E 'foo.*bar|bar.*foo'
    

现在得到NOT (foo AND bar)

grep -v -E 'foo.*bar|bar.*foo'

我不确定上面的方法在处理两种以上模式时是否是一个完整的系统。但你的一些问题仍然可以用它解决。例如:

AB+CDnonABnonCD

如果我没理解错的话AB+CD AND NOT (nonAB OR nonCD)

grep AB+CD | grep -v -e nonAB -e nonCD

请注意,这个请求使事情变得复杂:

我想打印只有“AB+CD”的行

有人可能会说grep ,AB+CD,AB+CD可以,但是由于“列数不固定”,我想你会想区分这两行:

youtube.com,9,AB+CD,AB+CD,AB+CD
youtube.com,9,AB+CD,AB+CD,banana

在这种情况下,您需要更复杂的正则表达式或其他工具(如awk)。

答案3

虽然你会在这里得到答案,但你应该看看人grep(可能会让人不知所措)和一些例子。暂时,答案如下:

使用grep

grep "foobar" test.txt

foobar将在文件中搜索包含单词的行test.txt并显示所有出现的情况,而

grep "foo" -v "bar" test.txt

将搜索包含单词foo但不包含单词的行bar。我们得到这个是因为-v开关手册页解释如下:

-v, --invert-match
    Invert the sense of matching, to select non-matching lines.
    (-v is specified by POSIX .)

这只是意味着它将搜索包含这些单词的行(此处bar),但最终显示时会排除它们。因此反转搜索

另外,要计算与搜索匹配的行数,请使用-c转变 :

-c, --count
    Suppress normal output; instead print a count of matching lines
    for each input file. With the -v, --invert-match option (see below),
    count non-matching lines. (-c is specified by POSIX .)

作为自我练习,尝试使用 grep 搜索文件福巴

答案

搜索AB+CD忽略nonABnonCD计数 URL:

grep "AB+CD" test | grep -cve "non"

此处-v "non"将忽略nonAB和 ,nonCD因为它们都包含non在内。 并且-c将给出匹配总数,而不是打印它们。 要打印匹配的行,只需忽略-c

您可以将其用于单独的反转:

grep "AB+CD" test | grep -cve "nonAB\|nonCD"

其中\|代表OR和 意味着nonABnonCD 精确的指定的单词-e转变。


建议你参见 Kamil 的回答,尽可能多地阅读手册页(您知道命令),努力在线搜索资料并为社区服务。请随意添加更多详细信息以进行回答。

相关内容