2016-08-30 51 views
1

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

在$字符串,我想淘汰的第一个“-1”,所以串的输出将是“测试测试测试Long.xml”。

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

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

我的问题是,我需要做的是同样的第一个“1”模式可选,如连字符和数量都不能有作为。

为什么“?”运算符不工作?我也尝试过{0,1},但没有运气。这一定是明显的东西...

+1

'$ string -replace'^(。*) - \ d + \ b(。*)\。xml $','$ 1 $ 2''是否按预期工作?您不需要任何可选组。请注意,如果不匹配,'replace'将返回字符串不变。 –

回答

1

正则表达式是贪婪使发动机不能决定匹配什么,这是不明确的。

不知道这是最好的解决办法,但我可以使它工作方式:

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

独家变化:第一组不得包含破折号:那种“平衡”的正则表达式,避免了greedyness和产量:

test test test-Long 

注意:输出不是test test test-Long.xml根据您的答案中的要求。要做到这一点,只需删除XML后缀:

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

这很适合'test test-1-Long.xml',但是通过输入'test test test-Long.xml'它会返回'test test testLong.xml',第一个连字符和第一个数字以及第二个连字符都需要是可选的。 – Laterade

+0

这会在'test test test-Long.xml'或'test test test-1Long.xml'的情况下做错误的事情。 '-1'可以在一个可选的非捕获组中:'(?: - \ d)?' –

+0

@PaulHicks这个工作,谢谢 – Laterade

0

$string -replace '^(.*?)(?:-\d+)?(-.*?)\.xml$', '$1$2'如存在连字符是在输入强制性应该工作。或者在输入可能没有连字符的情况下为$string -replace '^((?:(?!-\d+).)*)(?:-\d+)?(.*)\.xml$', '$1$2'

regex demo 1regex demo 2

图案的详细资料

  • ^ - 串的开始
  • (.*?) - 第1组捕获比换行符其他尽可能少任何0+字符(作为*?量词是懒惰)直到第一个(注意:为了增加正则表现,您可以使用基于脾气的贪婪令牌而不是(.*?) - ((?:(?!-\d+).)*)匹配任何te XT但- + 1 or more digits,从而,类似地起作用以否定的字符类,但对于符号序列)
  • (?:-\d+)? - 非捕获基团与贪婪?量词(因此,该基团具有用于正则表达式引擎更优先级,则前捕获该图案之前将结束)捕获一个连字符,接着用1个或多个数字
  • (-.*?) - 第3组捕获强制性-和比LF其他任何0+字符,尽可能少高达
  • \.xml - 文字文本.xml
  • $ - 字符串的结尾。

为什么“?”操作员不工作?

这是不正确的,因为它匹配量化子模式的一个或出现?行之有效的量词。然而,这个问题与第一个贪婪点匹配子模式.*相结合。请参见your regex in action:第一个捕获组捕获整个子串直到最后一个.xml,第二个组为空。为什么?

由于回溯和量词的贪婪是如何工作的。 .*尽可能匹配任何字符,但换行符。因此,它抓住了整个字符串到最后。然后,回溯开始:一次返回一个字符,并针对随后的子模式进行测试。他们是什么? -?\d?(-?.*) - 它们都可以匹配空字符串。 -?匹配.xml之前的空字符串,ok,\d?匹配那里,-?.*也匹配那里。然而,.*再次抓取整个字符串,但有\.xml模式来容纳。所以,第二个捕获组只是空的。事实上,正则表达式引擎执行的步骤更多(请参阅regex debugger页面),但主要想法就是这样。