grep-如何仅使用两个字符匹配正则表达式,但每个字符出现的次数相同?
使用 grep,我试图匹配由两个字符组成的行,一个是重复的,然后是另一个,但仅当第一个字符出现的次数等于第二个字符的出现次数时才匹配。
例如,假设我只能匹配两个字符,例如“0”和“1”。现在想象一下,如果有 n 个 '0' 字符,那么后面必须有 n 个 '1' 字符。例如:
- ''
- '0011'
- '000111'
- '00000000001111111111'
都会匹配。但:
- '011'
- '1100'
- '110001'
不匹配。
我一直在玩捕获组并通过 perldoc 搜索有关 grep -P 的更多信息,但还没有找到任何解决我问题的线索 - 至少使用 grep。
给定这些约束,我如何制作 grep 命令来匹配字符串?
编辑:
- 在此示例中,根据“紧随其后”的限制,0 应位于 1 之前
- 空字符串也应该是一个匹配案例,因为根据示例限制,当有 n 个 0 时,应该有 n 个 1,因此当有零个 0 时,应该有零个 1。
回答
有关说明的更新,请参阅下面的编辑
这是 Perl one-liner 而不是 grep
perl -wne'print if /^((.)g{-1}+)((.)g{-1}+)$/ and length $1 == length $3' file
匹配的长度比较显然是在正则表达式之外完成的;我不认为它可以在内部很好地完成†,而且我认为使用不是正则表达式的代码没有任何问题:)
这与单个字符 ( ab)不匹配,什么是没有意义的,什么似乎被排除在问题之外。锚点 (^和$) 使它只能匹配具有两个字符的字符串,这似乎是指定的。
这g{-1}是一个相对反向引用。它匹配上次捕获的相同子模式,这是我们需要的,而不是简单的反向引用 ( g1)。
这是需要的,因为g1指的是第一次捕获,括号集最先开始(最左边),也就是整个模式的捕获。(我们可以使用,g2但将它们计算在内是不好的做法。)
这可以通过使用命名引用变得更好,但它也会更加复杂。
编辑 根据澄清,它必须0先是 s 然后是相同数量的1s,并且0-repetitions 计数(所以是空行),1当然还有-repetition (所以01)。这大大简化了问题,因为
perl -wne'print if /^(0*)(1*)$/ and length $1 == length $2' file
该0和1可以制成其可作为外部参数如果需要,可以提供,(所以它可以是任何语法,变量a和b等等)。
它在问题的示例输入上按预期打印,因此在输入上 file
0011 000111 00000000001111111111 01 011 1100 110001
它打印
0011 000111 00000000001111111111 01
(输出中的最后一个空行是中间的空行,之后没有更多行匹配)
†也就是说,不使用在正则表达式中运行代码的棘手功能,这会使其变得更加复杂。如果您仍然希望使用它,请在 perlre
和
perlretut中查看它
。
或者,这也可以使用regex 中的递归来完成,具有相似(或稍低?)的复杂性。