bash 中两个字符串的最长公共前缀sed中的解决方案仅适用于 GNU 。我想要一个更便携的解决方案(例如对于 BSD/macOS 、 Busybox )。sedsedsedsed
以下解决方案已使用 GNU sed、macOS (10.15) sed 和 busybox (v1.29) sed 进行测试。
$ printf '%s\n' a ab abc | sed -e '$q;N;s/^\(.*\).*\n\1.*$/\1/;h;G;D'
a
$ printf '%s\n' a b c    | sed -e '$q;N;s/^\(.*\).*\n\1.*$/\1/;h;G;D'
$
Run Code Online (Sandbox Code Playgroud)
当有很多字符串时,尤其是根本没有公共前缀时,为了提高效率(注意..*与之前的解决方案不同的部分):
$ printf '%s\n' a ab abc | sed -ne :L -e '$p;N;s/^\(..*\).*\n\1.*/\1/;tL' -e q
a
$ printf '%s\n' a b c    | sed -ne :L -e '$p;N;s/^\(..*\).*\n\1.*/\1/;tL' -e q
$
Run Code Online (Sandbox Code Playgroud)
$q第一个解决方案根据 GNU sed 手册 ( info sed):
N命令在最后一行当在文件的最后一行发出命令 时,大多数版本的
sed退出都不打印任何内容。在退出之前打印模式空间,当然除非已指定命令开关。NGNU sed-n
请注意,我没有使用sed -E,因为 macOSsed -E不支持命令模式\N部分中的反向引用。s/pattern/replace/
使用 GNU sed:
$ echo foofoo | gsed -E 's/(foo)\1/bar/'
bar
Run Code Online (Sandbox Code Playgroud)
对于 macOS sed:
$ echo foofoo | sed  -E 's/(foo)\1/bar/'
foofoo
Run Code Online (Sandbox Code Playgroud)
在另一个答案中找到了这个:
sed -e '1{h;d;}' -e 'G;s/\(.*\).*\n\1.*/\1/;h;$!d'
Run Code Online (Sandbox Code Playgroud)
请注意,当输入仅包含一行时,它不起作用。通过移除该部件即可轻松修复1d:
sed -e '1h;G;s/^\(.*\).*\n\1.*/\1/;h;$!d'
Run Code Online (Sandbox Code Playgroud)