[user@notebook ~]$ printf 'adgaa alpha lajsd assa ><>4 saf\n63SXYZae fkrk safXYZek\nsaf betf!%saa sDGFXYZFalf\n'
adgaa alpha lajsd assa ><>4 saf
63SXYZae fkrk safXYZek
saf betf!aa sDGFXYZFalf
[user@notebook ~]$
[user@notebook ~]$ printf 'adgaa alpha lajsd assa ><>4 saf\n63SXYZae fkrk safXYZek\nsaf betf!%saa sDGFXYZFalf\n' | grep SOMEMAGIC
63SXYZae fkrk safXYZek
[user@notebook ~]$
问题:如何 grep 只查找那些具有给定字符串两次的行?在此示例中,字符串为“XYZ”。两根弦之间,可能有任何东西。
答案1
grep 两次不会给你带来任何好处。我会选择将egrep与符合您需要的正则表达式结合使用。
ps ax | egrep '(a.*){2}'
这将为您提供所有具有两次“a”的进程。当然,您可以在egrep可以读取的任何类型的输入上使用它。
答案2
使用正则表达式,您可以反向引用分组(
模式)
,或者您可以指定匹配必须{
重复}
它。其中一个和另一个之间的差异是显着的。举一个简单的例子,考虑一下字符串:
baa
...当与以下两种模式匹配时:
\([ba]\)\{2\}
\([ba]\)\1
对于第一个,分组实际上是无关的,因为模式搜索单个字符 - 当指定重复时,分组的唯一重要之处在于它可以包含重复可以引用的整个子表达式。因此,对于这个简单的示例案例......
[ba]\{2\}
... 和 ...
\([ba]\)\{2\}
...是同义的,可以理解为匹配引擎应该在输入中查找由两个字符组成的最左边和最长的字符串 - 任意一个乙或者A。重复适用于图案这使得匹配和不是到比赛的内容。所以它的字面意思是:
[ba][ba]
....以同样的方式...
\(a.*\)\{2\}
...方法...
a.*a.*
...对于单个角色来说这可以正常工作A但这并不是如何再次匹配匹配字符串的好例子。
对于我们的输入样本,这得到......
ba
但反向引用非常不同——它是对比赛内容。简单的示例案例...
aa
...因为这是输入中最左边且最长的字符串,由与子表达式的模式匹配的字符组成[ba]
,并且紧随其后本身- 不是与字符匹配的模式。
所以你要:
\(pattern\).*\1
因为正则表达式图案并且它匹配的字符串不相同 - 否则我们一开始就不会有太多调用使用正则表达式。为了用稍微复杂的输入示例来演示差异,请考虑以下内容:
printf %s\\n 123ABC321 123ABC123 321ABC321 |
grep '\([123]\{3\}.*\)\{2\}'
上面grep
将打印:
123ABC321
123ABC123
321ABC321
...因为在每种情况下图案匹配成功两次。但如果该grep
行替换为:
grep '\([123]\{3\}\).*\1'
...它只会打印...
123ABC123
321ABC321