可移植的 sed 方法来查找字符串的最长公共前缀

pyn*_*exj 2 sed

bash 中两个字符串的最长公共前缀sed中的解决方案仅适用于 GNU 。我想要一个更便携的解决方案(例如对于 BSD/macOS 、 Busybox )。sedsedsedsed

pyn*_*exj 5

以下解决方案已使用 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/


更新(2021-04-26):

在另一个答案中找到了这个:

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)