替换参数剥离它不应该的空间

问题描述 投票:1回答:3

我对以下替换语句有一个理解问题。

'Select {0}' -replace '[^\\](\{0\})', 'Success'

我希望:选择成功

相反,结果是:SelectSuccess

'[^\\](\{0\})'模式可以通过以下方式解构:

  • 匹配单个字符NOT不在列表'\'中
  • 匹配内部模式并捕获其匹配 从字面上匹配字符'{' 从字面上匹配字符'0' 从字面上匹配字符'}'

如果我删除了非部分[^\\]。然后结果再次成为选择成功

我错过了什么吗?

regex powershell
3个回答
2
投票

正如LotPings在评论中指出的那样,问题是[^\\]匹配{0}之前的空格字符,因此被替换的完整匹配是 {0},这解释了为什么结果是SelectSuccess

解决方案是使用negative look-behind assertion

Select {0}' -replace '(?<!\\)\{0\}', 'Success'

(?<!\\)确保子表达式\{0\}不是(!),前面是((?<...\ char。 (\\)不包括那个字符。在比赛中。

正如LotPings也指出的那样,你在正则表达式中使用捕获组((...))没有任何效果,因为你既没有将它称为正则表达式(\1)本身内的反向引用,也没有将其称为替换操作数($1)。

请注意,无论捕获组如何,-replace总是取代正则表达式整体捕获的内容。要匹配输入的部分而不将其包含在捕获的结果中,请使用look-around assertions,如上所示。


2
投票

编者注:这个答案显示了PowerShell中可用的一般字符串格式化技术,但在OP的特定情况下,它的使用不是一个选项,因为需要条件字符串替换。

你知道-f的operator.of吗? PowerShell能够像在.net中一样进行字符串格式化。

例:-

'Select {0}' -f 'Success'

'Select {0} {1}' -f 'All','Files'

请参阅下面的文章,了解它是如何在.Net中完成的,同样可以使用-f完成

https://docs.microsoft.com/en-us/dotnet/api/system.string.format?view=netframework-4.7.2#examples


1
投票

你想做两件事:

  • 找到{0}不是以逃脱的{开始,考虑到在\\之前可以有一个{表示字面反斜杠(使用(?<=(?<!\\)(?:\\{2})*)\{0\}正则表达式并用Success替换)
  • “Unescape”都逃脱了字符,其中逃脱字符是字面反斜杠(使用(?s)\\(.)正则表达式并替换为$1

使用

'Select \\\{0}' -replace '(?<=(?<!\\)(?:\\{2})*)\{0\}', 'Success' -replace '(?s)\\(.)', '$1'

模式1详细信息

  • (?<=(?<!\\)(?:\\{2})*) - 一个正面的背后,立即在当前位置的左侧,需要 (?<!\\) - 没有\立即允许在当前位置的左侧 (?:\\{2})* - 重复0次或更多次双反斜杠
  • \{0\} - {0}字符串。

regex demo

模式2细节

  • (?s) - 一个RegexOptions.Singleline选项,使.能够匹配换行
  • \\ - 一个字面反斜杠
  • (.) - 捕获组1:任何字符(在匹配替换后它将被放回到结果字符串中)。

this regex demo

© www.soinside.com 2019 - 2024. All rights reserved.