我正在尝试执行以下操作:
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
它是获得匹配,然后您转身并将匹配的值替换回您找到的位置。注意.*
不能匹配任何东西后 $
。
想必您想要类似except 的东西,因为 sed 会贪婪地将所有内容消耗到s:.*([^/]*$):\1:
.*
.你可以在 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 的 shell 中执行此操作,您可能会发现使用 shell 参数扩展来删除最长路径匹配更简单:
$ var="/Users/anon/Applications/Chrome Apps.localized/Spotify.app"
$ echo "${var##*/}"
Spotify.app