Powershell中的可选正则表达式运算符

时间:2016-08-30 22:00:05

标签: regex powershell

如果这是一个非常简单的问题我很抱歉。我第一次在Powershell中使用正则表达式...

在$ string中,我试图淘汰第一个" -1"所以字符串的输出将是"测试测试test-Long.xml"。

 $string = 'test test test-1-Long.xml'

 $string -replace '^(.*)-?\d?(-?.*)\.xml$', '$1$2'

我的问题是我需要先做同样的事情" -1"模式可选,因为连字符和数字都不能存在。

为什么" ?"操作员不工作?我也在每次尝试{0,1}之后也没有运气。这必须是显而易见的......

2 个答案:

答案 0 :(得分:1)

正则表达式是贪婪的,所以引擎无法决定匹配什么,这是不明确的。

不确定这是最好的解决方案,但我可以这样做:

$string -replace '^([^\-]*)-?\d?(-?.*)\.xml$', '$1$2'
唯一的变化:第一组不得包含破折号:那种“平衡”正则表达式,避免贪婪并产生:

test test test-Long

注意:答案中的输出不是test test test-Long.xml。为此,只需删除xml后缀:

$string -replace '^([^\-]*)-?\d?(-?.*)', '$1$2'

答案 1 :(得分:0)

如果输入中必须使用连字符,则$string -replace '^(.*?)(?:-\d+)?(-.*?)\.xml$', '$1$2'应该有效。或$string -replace '^((?:(?!-\d+).)*)(?:-\d+)?(.*)\.xml$', '$1$2'以防输入可能没有连字符。

请参阅regex demo 1regex demo 2

模式详情

  • ^ - 字符串开头
  • (.*?) - 第1组捕获除换行符之外的任何0 +字符尽可能少(因为*?量词是 lazy )直到第一个(注意:为了提高正则表达式的性能,您可以使用基于驯化贪婪令牌的模式而不是(.*?) - ((?:(?!-\d+).)*)来匹配除- + 1 or more digits以外的任何文字因此,类似于否定的字符类,但对于一系列符号)
  • (?:-\d+)? - 具有贪婪?量词的非捕获组(因此,此组具有更高优先级的正则表达式引擎,之前的捕获将在此模式之前结束)捕获连字符后跟1或更多数字
  • (-.*?) - 第3组捕获强制性-和除LF以外的任何0+字符,尽可能少
  • \.xml - 文字.xml
  • $ - 字符串结束。
  

为什么"?"操作员不工作?

不是这样,量词?运行良好,因为它匹配量化子模式的一个或次出现。但是,问题出现在第一个.*贪婪点匹配子模式的组合中。请参阅your regex in action:第一个捕获组抓取整个子字符串直到最后.xml,第二个组为空。为什么呢?

由于回溯以及量词的贪婪程度如何。 .*匹配任何字符,但新行尽可能多。因此,它将整个字符串抓到最后。然后,开始回溯:一次返回一个char并对后续的子模式进行测试。这些是什么? -?\d?(-?.*) - 所有这些都可以匹配一个空字符串。 -?.xml之前匹配空字符串,ok,\d?也匹配,-?.*也匹配。但是,.*再次抓取整个字符串,但可以容纳\.xml模式。所以,第二个捕获组只是空的。事实上,正则表达式引擎执行的步骤更多(参见regex debugger页面),但主要思想就是这样。