在正则表达式中特殊地使用'*'

时间:2017-06-01 19:22:11

标签: regex python-3.6

在编写正则表达式模式时,将所有连续体'1'和单个'1'替换为's'。我发现这很混乱,使用'+'(用于匹配1或更多)给出了预期的结果,但'*'给出了奇怪的结果

>>> l='100'
>>> import re
>>> j=re.compile(r'(1)*')    
>>> m=j.sub('*',l)
>>> m
'*0*0*'

虽然使用'+'给出了预期的结果。

>>> l='100'
>>> j=re.compile(r'1+')
>>> m=j.sub('*',l)
>>> m
'*00'

正则表达式中的'*'如何给出这个,而它的行为是匹配0或更多。

3 个答案:

答案 0 :(得分:6)

(1)*表示"匹配0或更多1' s"。因此,对于100,它匹配1,0到0之间的空字符串,以及最后一个0之后的空字符串。然后用' *'替换空字符串。 1+在比赛中至少需要一个1,所以它不会匹配角色之间的边界。

对于那些好奇的读者,是的,python输出是*0*0*而不是**0*0*。这是一个测试python script。 (Regex101的输出错误,因为它不使用实际的python正则表达式引擎。在线正则表达式测试人员通常会使用PCRE(在PHP和Apache HTTP Server中提供),并伪造目标正则表达式引擎。总是测试你的正则表达式在实时代码!)

在这里,您可以在JavaScript中看到输出将是**0*0*(它将匹配1和0之间的空字符串作为新匹配)这是为什么正则表达式的原因'很重要不同引擎使用略有不同的规则。 (在这种情况下,如果新匹配从0开始或字符边界开始)



console.log("100".replace(/(1)*/g, '*'))




答案 1 :(得分:2)

谨防那些无法​​匹敌的模式。这个定义不明确,因此行为因引擎而异。例如,您在Perl中获得了不同的结果。

$log = "C:\Users\IP_Address.txt"
$DB=@()
$DB = Get-Content C:\Users\Hostname.txt

## Loop through each line in IP_Address.txt to do the replacement, as needed
Get-Content $log | ForEach-Object {

    ## Perform work if we run into a line with an IP
    if ($_ -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
        $DBE = $DB | ? { $_ -like "$($_)*" }

        ## Make sure the entry we get back is a valid IP
        if ($DBE -match '(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
            $_.Replace($_, $DBE)  ## Replace just the IP with the IP/hostname from hostname.txt
        } else {
            $_  ## Else just emit the line as-is which still contains the original IP
        }
    } else {
        $_
    }
}
  1. 在第0位,它匹配1个字符。
  2. 在第1位,它匹配0个字符。
  3. [被迫前进以避免无限循环]
  4. 在第2位,它匹配0个字符。
  5. [被迫前进以避免无限循环]
  6. 在第3位,它匹配0个字符。
  7. [被迫前进以避免无限循环]
  8. [不匹配:超越字符串结尾]

答案 2 :(得分:2)

regex = r"1*"
p = re.compile(regex)
test_str = "100"
for m in p.finditer(test_str):
    print(m.start(), m.group())

输出4场比赛(这就是为什么regex101显示4场比赛):

0 1
1 
2 
3 

虽然re.sub()替换了3个位置,这是re.sub()在零长度匹配(Python doc)之后前进的原因:

  

sub(pattern,repl,string,count = 0,flags = 0)

     

返回通过替换最左边的非重叠出现而获得的字符串   替换 repl 的字符串中的 pattern

     

...

     

仅当不与a相邻时,才会替换模式的空匹配   上一场比赛,sub('x*', '-', 'abc')返回'-a-b-c-'

非重叠事件意味着什么? It means when

  

第一个匹配在字符串的开头结束,第一个匹配   比赛尝试开始了。正则表达式引擎需要一种避免获取的方法   卡在无限循环中,永远找到相同的零长度   在字符串的开头匹配。

     

大多数正则表达式引擎使用的最简单的解决方案是   在结束后开始下一个匹配尝试一个字符   上一场比赛,如果前一场比赛是零长度。

在这种情况下,第二次匹配尝试从字符串中1和0之间的位置开始,因此是差异。