从Bash中的字符串中删除固定的前缀/后缀

Remove a fixed prefix/suffix from a string in Bash

在我的bash脚本中,我有一个字符串及其前缀/后缀。 我需要从原始字符串中删除前缀/后缀。

例如,假设我有以下值:

1
2
3
string="hello-world"
prefix="hell"
suffix="ld"

我如何得到以下结果?

1
result="o-wor"


1
2
3
4
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo"${foo}"
o-wor


使用sed:

1
2
$ echo"$string" | sed -e"s/^$prefix//" -e"s/$suffix$//"
o-wor

在sed命令中,^字符匹配以$prefix开头的文本,尾随$匹配以$suffix结尾的文本。

AdrianFrühwirth在下面的评论中提出了一些好处,但sed为此目的非常有用。 $ sed和$ suffix的内容由sed解释的事实可能是好的或坏的 - 只要你注意,你应该没事。美丽的是,你可以这样做:

1
2
3
4
$ prefix='^.*ll'
$ suffix='ld$'
$ echo"$string" | sed -e"s/^$prefix//" -e"s/$suffix$//"
o-wor

这可能是你想要的,并且比bash变量替换更有魅力和更强大。如果你记得有很大的力量就会有很大的责任(正如蜘蛛侠说的那样),你应该没事。

有关sed的快速介绍,请访问http://evc-cit.info/cit052/sed_tutorial.html

关于shell及其字符串使用的注释:

对于给出的特定示例,以下内容也可以使用:

1
$ echo $string | sed -e s/^$prefix// -e s/$suffix$//

......但仅仅是因为:

  • echo不关心它的参数列表中有多少个字符串,以及
  • $ prefix和$ suffix中没有空格
  • 在命令行中引用字符串通常是一种好习惯,因为即使它包含空格,它也会作为单个参数显示给命令。我们引用$ prefix和$ suffix的原因相同:sed的每个edit命令都将作为一个字符串传递。我们使用双引号,因为它们允许变量插值;如果我们使用单引号,sed命令会得到一个文字$prefix$suffix,这肯定不是我们想要的。

    另请注意,在设置变量prefixsuffix时我使用单引号。我们当然不希望对字符串中的任何内容进行解释,因此我们单引引它们以便不进行插值。同样,在这个例子中可能没有必要,但这是一个非常好的习惯。


    你知道你的前缀和后缀的长度吗?在你的情况下:

    1
    result=$(echo $string | cut -c5- | rev | cut -c3- | rev)

    或者更一般:

    1
    result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)

    但AdrianFrühwirth的解决方案很酷!我不知道那个!


    我使用grep从路径中删除前缀(sed处理不好):

    1
    echo"$input" | grep -oP"^$prefix\K.*"

    \K从匹配中删除之前的所有字符。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ string="hello-world"
    $ prefix="hell"
    $ suffix="ld"

    $ #remove"hell" from"hello-world" if"hell" is found at the beginning.
    $ prefix_removed_string=${string/#$prefix}

    $ #remove"ld" from"o-world" if"ld" is found at the end.
    $ suffix_removed_String=${prefix_removed_string/%$suffix}
    $ echo $suffix_removed_String
    o-wor

    笔记:

    #$ prefix:adding#确保只有在开头找到子字符串"hell"才会被删除。
    %$后缀:添加%确保只有在end中找到子字符串"ld"才会被删除。

    如果没有这些,子串"地狱"和"ld"将在任何地方被移除,即使它位于中间。


    小而通用的解决方案:

    1
    expr"$string" :"$prefix\(.*\)$suffix"


    使用=~运算符:

    1
    2
    3
    4
    5
    $ string="hello-world"
    $ prefix="hell"
    $ suffix="ld"
    $ [["$string" =~ ^$prefix(.*)$suffix$ ]] && echo"${BASH_REMATCH[1]}"
    o-wor

    使用@AdrianFrühwirth回答:

    1
    2
    3
    4
    function strip {
        local STRING=${1#$"$2"}
        echo ${STRING%$"$2"}
    }

    像这样使用它

    1
    2
    3
    HELLO=":hello:"
    HELLO=$(strip"$HELLO"":")
    echo $HELLO # hello