正则表达式:相同字符串不同位置的结果不同

时间:2017-08-14 01:14:19

标签: regex bash

要求:
1.必须包含至少一个小写字符[a-z]
2.必须包含至少一位数字\ d
这是我的模式\b(?=[^a-z]*[a-z])(?=\D*\d)\w+\b

match='\b(?=[^a-z]*[a-z])(?=\D*\d)\w+\b'
str1="12AAayuA 12345"
str2="12AAayuA 12345 12AAayuA 12345"
echo $str1 |grep -oP  $match
12AAayuA    
echo $str2 |grep -oP  $match
12AAayuA
12345
12AAayuA

为什么echo $str2 |grep -oP $match的结果不是以下内容?

12AAayuA
12AAayuA

使用Anthony的正则表达式:\b(?=[A-Z0-9]*[a-z])(?=\D*\d)\w+\b,让它为$ fixed-match。

echo $str2 |grep -oP  $fixed-match
12AAayuA
12AAayuA

我的问题仍然存在,因为我的正则表达有一个错误,
为什么12345可以在echo $str2 |grep -oP $match而不是echo $str1 |grep -oP $match中搜索?{。} echo $str2 |grep -oP $match的工作流程是什么? echo $str2 |grep -oP $match如何导致:

12AAayuA
12345
12AAayuA

不是

12AAayuA
12AAayuA

而不是

12AAayuA
12345
12AAayuA
12345

3 个答案:

答案 0 :(得分:2)

了解前瞻

原因是你误用了前瞻的窗户。

使用超前窗口时,它只向前看。 它不会捕获因此总而言之,在使用(?=[^a-z]*[a-z])(?=\D*\d)时,您实际上并未捕获任何内容,而这些只是在验证前面的条件。捕获是使用\b\w\b完成的。所以考虑到这一点,让我们重新解释你的正则表达式。

它表示查找以单词边界开头的字符串,然后验证单词边界后面跟着这些条件再继续...从这里开始我们验证可能< / strong>是一些非小写的数字,为小写数字,可能一些非数字,为数字。< / p>

Str1的细分

str1="12AAayuA 12345"开始,然后从12345开始,

它以字边界开头,很好。但?=[^a-z]*[a-z]前瞻不满意,因为它不以字符结尾。

Str2的细分

现在点击str2="12AAayuA 12345 12AAayuA 12345"并从12345 12AAayuA 12345

开始

它以字边界开头,很好。现在展望未来,?=[^a-z]*[a-z]已满足,因为12345 12AA不是小写字符,但12345 12AA后面的后续字符是小写字符。

现在我们转移到(?=\D*\d)但是等待,前瞻窗口向前看表达式是回溯窗口,但同样是\b。因此,从12345 12AAayuA 12345开始,我们评估(?=\D*\d),这是真的

现在我们可以捕获前瞻性。因此,从12345 12AAayuA 12345开始,我们捕获剩余的\w+\b,这就是您获得12345

的原因

什么是正确的解决方案?

我会去 \b(?=\w*[a-z])(?=\w*\d)\w*\b

  • 找到单词的开头
  • 检查单词是否包含小写
  • 检查单词是否有数字
  • 然后捕获/匹配

答案 1 :(得分:1)

你的前瞻断言中的字符集[^ a-z]可能过于宽松,因为它还包括单词之间的空格。

为了强调您可以尝试以下测试:

\b(?=[A-Z0-9]*[a-z])(?=\D*\d)\w+\b

答案 2 :(得分:1)

这是一个非常复杂的正则表达式,几乎没有任何小缺陷会对结果产生重大影响。正如@Anthony所提到的,一个缺陷,

  

你的前瞻断言中的字符集[^ a-z]也可能是这样   宽容,因为它还包括单词之间的空格。

让我们退一步看看要求。

因此,您希望正则表达式验证带有小写字母和数字的字符串。 让我们回顾一下可以满足这两个条件的所有可能方法。 有两种格式可以成立( RA表示随机字母数字字符):

  • RA +小写+ RA +号码+ RA (\w*[a-z]+\w*\d+\w*)
  • RA +号码+ RA +小写+ RA (\w*\d+\w*[a-z]+\w*)

现在我们只需将这些组合成一个由|分隔的正则表达式。它有点长,但它完成了工作。

\b(\w*[a-z]+\w*\d+\w*)|(\w*\d+\w*[a-z]+\w*)\b