Regex 为什么替换运算符与powershell中的空字符串匹配

Regex 为什么替换运算符与powershell中的空字符串匹配,regex,powershell,replace,Regex,Powershell,Replace,在Powershell(5.1或7)中,我运行: 正如您所看到的,在第一次运行中,我得到了xx,但希望得到一个x。 在bash中尝试了sed(我想是来自gitdir/usr/bin;msys的可执行文件),得到了我所期望的结果 2021-05-01 01:34:27 /r : $ echo "abcdef" | sed -E s/.*/x/g x 2021-05-01 01:35:03 /r : $ echo "abcdef" | sed -E s/.+

在Powershell(5.1或7)中,我运行:

正如您所看到的,在第一次运行中,我得到了
xx
,但希望得到一个
x
。 在bash中尝试了sed(我想是来自gitdir/usr/bin;msys的可执行文件),得到了我所期望的结果

2021-05-01 01:34:27 /r :
$ echo "abcdef" | sed -E s/.*/x/g
x

2021-05-01 01:35:03 /r :
$ echo "abcdef" | sed -E s/.+/x/g
x

2021-05-01 01:35:08 /r :
$ echo "abcdef" | sed -E s/^.*/x/g
x

2021-05-01 01:35:17 /r :
$ echo "abcdef" | sed -E s/^.+/x/g
x

2021-05-01 01:35:20 /r :
$ echo "abcdef" | sed -E s/^/x/g
xabcdef

2021-05-01 01:35:25 /r :
$
我已经尝试了文档,但不知道如何理解正在发生的事情。

让我们来看看

在任何版本的PowerShell中,找出正则表达式模式所匹配内容的最简单方法是使用
regex.Matches()

啊哈!它匹配子字符串
abcdef
,然后匹配
f
和字符串末尾之间的空字符串


在PowerShell 7中,我们还可以使用带有替换运算符的脚本块来确认:

PS ~> "abcdef" -replace '.*',{"['$($_.Value)' (length $($_.Length)) starting at $($_.Index)]"}
['abcdef' (length 6) starting at 0]['' (length 0) starting at 6]

恐怕我现在不明白为什么正则表达式引擎实现者认为这种行为比sed的行为更可取,但至少我们知道现在发生了什么。

选择显示2个匹配项的字符串:

# select-string highlights matches in ps 7, but you can't see the 2nd match anyway
'abcdef' | select-string .* -AllMatches | % matches   # 2 matches
看起来像是.Net的东西,即使在Powershell 7中也是如此。也给出了2个匹配项,所以可能是sed错了(“posix?”.net应该遵循该标准吗?),因为/g表示全局或所有匹配项

[regex]::Replace('abcdef','.*','x')

xx
只替换一次():

在osx中,其工作原理与sed相同。由于某些原因,它只能在bash中工作。哦,您必须在powershell中反斜杠所需的双引号

echo 'abcdef' | awk '{ gsub(/.*/,\"x\"); print }'

x

似乎这是一种正则表达式行为,而不是特定的powershell。返回2个匹配项。不过我无法解释。可能是因为第一个匹配是零匹配,其余的是一个或多个匹配。(在正则表达式中,asteriks表示零个或多个匹配)?Theo不,这是另一种方式-第一个匹配是
abcdef
,第二个是
f
和string@MathiasR.Jessen但愿上帝知道!。我通过锚定到字符串
“abcdef”-replace.*$,“x”
-->
xx
,同时锚定到字符串的开头
“abcdef”-replace'^.*',“x”
返回单个
x
这是RegexBuddy对它的理解-在选择
.NET
时会显示相同的警告,因此看起来像是一般的
.NET
thingNice演示;至于原因:长时间的讨论,但对我来说仍然没有充分的意义。@mklement0有一条关于sed和awk的“posix最左最长匹配”的评论。Regex101.com显示了2个匹配项。@mklement0有趣的观察结果。之前我并没有认真考虑过,我最初的直觉实际上是“sed很奇怪,很友好,.NET的行为就像我所期望的那样”,正如你在中途指出的(即“位置N是macthing的一个完全有效的偏移量”)是的,
sed
awk
(BSD/macOS和GNU/Linux实现在全球范围内只匹配一次
*
;mawk的情况也是如此。Python2.x和Python到v3.6也只匹配一次,但从我所知的情况来看,大多数引擎匹配两次。一个例外是不幸需要
\
-逃避
chars.PowerShell Core 7.2.0-preview.5引入了实验性功能
PSNativeCommandArgumentPassing
,这使得它不再是必需的;它在Unix平台上运行良好,但在Windows上缺少重要的调整;此外,目前还存在一些错误-请参阅。很好,感谢带有解释的regex101链接。
[regex]::Replace('abcdef','.*','x')

xx
$pattern = [regex]'.*'
$pattern.replace('abcdef','x',1)

x
echo 'abcdef' | awk '{ gsub(/.*/,\"x\"); print }'

x