在编写正则表达式模式时,将所有连续体'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或更多。
答案 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 {
$_
}
}
答案 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之间的位置开始,因此是差异。