Sed

無法匹配組

  • May 17, 2022

我正在嘗試執行以下操作:

echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
sed -E 's:([^\/]*$).*:\1:'

我認為它會擷取Spotify.app並用它替換整個字元串,但這不起作用。相反,我得到了整個字元串。

所以,我想也許我的正則表達式是錯誤的,所以我做了下面的測試:

echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" |
sed 's:[^\/]*$:PWA.app:' 

但我得到了預期的輸出:/Users/anon/Applications/Chrome Apps.localized/PWA.app.

所以,我不確定我在這裡做錯了什麼。為什麼分組時相同的正則表達式不匹配?

你讓它變得比它需要的更複雜。

sed -e 's:.*/::'

讓正則表達式的貪婪為您完成工作。將.*很快一直過衝到字元串的末尾,但隨後它需要匹配一個硬斜杠,因此正則表達式引擎開始回溯,尋找 / 並在返回途中遇到的第一個 / 處停止。=> 字元串的最後一個斜杠。我們只是刪除直到這一點,我們隱含地留下最後一個斜線和字元串結尾之後的內容。

正在匹配,然後您轉身並將匹配的值替換回您找到它的位置。請注意,之後.*不能匹配任何內容。 $

大概你想要類似的東西,s:.*([^/]*$):\1:除了那不起作用,因為 sed 會貪婪地將所有東西都消耗到.*. 你可以在 perl 中使用 non-greedy 修飾符來做到這一點:

$ echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" | 
   perl -pe 's:.*?([^/]*$):\1:'
Spotify.app

/在 sed 中,您可以通過匹配 0 個或多個終止的路徑組件來偽造非貪婪:

$ echo "/Users/anon/Applications/Chrome Apps.localized/Spotify.app" | 
   sed -E 's:([^/]*/)*(.*)$:\2:'
Spotify.app

但是,如果您在任何支持 POSIX 的 shell 中執行此操作,您可能會發現使用 shell 參數擴展來刪除最長路徑匹配更簡單:

$ var="/Users/anon/Applications/Chrome Apps.localized/Spotify.app"
$ echo "${var##*/}"
Spotify.app

引用自:https://unix.stackexchange.com/questions/702788