2016-08-30 52 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頁面),但主要想法就是這樣。