【问题标题】:Portable sed way to find longest common prefix of strings便携式 sed 方法来查找字符串的最长公共前缀
【发布时间】:2020-12-11 04:24:44
【问题描述】:

Longest common prefix of two strings in bash 中的sed 解决方案仅适用于 GNU sed。我想要一个更便携的 sed 解决方案(例如,用于 BSD/macOS 的 sed,Busybox sed)。

【问题讨论】:

    标签: shell sed


    【解决方案1】:

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

    在有很多字符串时更高效,尤其是在根本没有公共前缀的情况下(注意 ..* 部分,这与之前的解决方案不同):

    $ 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
    $
    

    关于第一个解决方案中的$q

    根据 GNU sed 手册 (info sed):

    • N 命令在最后一行

      当在文件的最后一行发出N 命令时,大多数版本的sed 退出而不打印任何内容。 GNU sed 在退出之前打印模式空间,当然除非指定了 -n 命令开关。


    请注意,我没有使用sed -E,因为macOS sed 的-E 不支持s/pattern/replace/ 命令的模式 字符串中的\N 反向引用。

    $ # with GNU sed:
    $ echo foofoo | gsed -E 's/(foo)\1/bar/'
    bar
    $
    $ # with macOS's own sed:
    $ echo foofoo | sed  -E 's/(foo)\1/bar/'
    foofoo
    $
    

    更新(2021-04-26):

    在另一个 answer 中找到这个:

    sed -e '1{h;d;}' -e 'G;s/\(.*\).*\n\1.*/\1/;h;$!d'
    

    请注意,只有一行时它不起作用。可以通过删除1d 部分轻松修复:

    sed -e '1h;G;s/^\(.*\).*\n\1.*/\1/;h;$!d'
    

    【讨论】:

      猜你喜欢
      • 2021-02-14
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 2018-05-07
      • 2017-08-03
      • 1970-01-01
      • 2011-12-23
      相关资源
      最近更新 更多