グループと一致するようにsedを取得できません

グループと一致するようにsedを取得できません

私は次のことをしようとしています:

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

だからここで何が間違っているのかわかりません。グループ化するときに同じ正規表現が一致しないのはなぜですか?

答え1

必要以上に複雑にしています。

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

貪欲な正規表現が代わりに機能するようにしてください。.*すぐに文字列の終わりを通過しますが、ハードスラッシュと一致する必要があるため、正規表現エンジンは逆追跡を開始し、/を探して戻りに最初に会う/で停止します。 => 文字列の最後のスラッシュです。この点までのみ削除し、最後のスラッシュと文字列の終わり以降のすべての内容を暗黙的に残します。

答え2

それはい一致するものを取得し、戻って一致する値を見つけた場所に戻します。どんなものとも.*一致できません。後ろに $

s:.*([^/]*$):\1:おそらくあなたはsedがすべてのものを貪欲に消費するので、Exceptのようなものが欲しいでしょう.*。 non-greedy修飾子を使用してPerlでこれを行うことができます。

$ 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対応シェルでこれを行う場合は、シェルパラメータ拡張を使用して最長のパス一致を削除する方が簡単になる可能性があります。

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

関連情報