[英]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 grep
或pcregrep
,您可以使用
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.