繁体   English   中英

如何将仅包含模式的单个实例的行与 grep 匹配?

[英]How can I match a line containing only a single instance of a pattern with grep?

给定一个像这样的文本文件,说phrases.txt的内容:

Hahahahahasdhfjshfjshdhfjhdf
Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
Hahaha!Hahaha!
dfhjfsf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs
Ha! Ha! Ha!

什么是 bash 中合适的grep命令,它只输出仅包含一次大笑的行,其中大笑被定义为Hahahahaha!形式的字符串Hahahahaha! 有任意多的ha 第一个H总是大写,其他的不是,并且字符串必须以! . 在我的示例中, egrep 命令应该输出:

Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs

我想出的命令是:

egrep "(Ha(ha)*\!){1}" phrases.txt

我的命令的问题在于它不仅输出只有一次笑声的行。 使用我的命令,第 4 行( Hahaha!Hahaha! )和第 8 行( Ha! Ha! Ha! )也被打印出来,这不是我想要的。

有没有一种只用 grep 来做到这一点的好方法?

那么你对管道没问题

egrep '(Ha(ha)*!)' yourfile.txt | egrep -v '(Ha(ha)*!).*(Ha(ha)*!)'

首先过滤至少一个笑声,然后过滤掉不止一个笑声的那些。

注意: {1}只重复前一个块,它不会检查字符串的其余部分以坚持只有一个。 所以a{1}a实际上是一样的。

如果您使用支持 PCRE 正则表达式的 GNU greppcregrep ,您可以使用

grep -P '^(?!(?:.*Ha(ha)*!){2}).*Ha(ha)*!'

图案是:

^(?!(?:.*YOUR_PATTERN_HERE){2}).*YOUR_PATTERN_HERE

其中YOUR_PATTERN_HERE代表您希望在字符串中只出现一次的模式。

细节

  • ^ - 字符串的开始
  • (?!(?:.*YOUR_PATTERN_HERE){2}) - 匹配失败的负向前瞻,紧靠当前位置(这里是字符串的开头)的右侧,连续出现两次
    • .* - 除换行符以外的任何 0+ 个字符
    • YOUR_PATTERN_HERE - 您需要的模式
  • .* - 除换行符以外的任何 0+ 个字符
  • YOUR_PATTERN_HERE - 您所需的模式。

请参阅在线演示

s="Hahahahahasdhfjshfjshdhfjhdf
Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
Hahaha!Hahaha!
dfhjfsf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs
Ha! Ha! Ha!"
echo "$s" | grep -P '^(?!(?:.*Ha(ha)*!){2}).*Ha(ha)*!'

输出:

Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM