我想从字符串中删除前缀/后缀。例如,给定:

string="hello-world"
prefix="hell"
suffix="ld"

如何得到以下结果?

"o-wor"

当前回答

使用sed:

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

在sed命令中,^字符匹配以$前缀开头的文本,后面的$匹配以$后缀结尾的文本。

Adrian Frühwirth在下面的评论中提出了一些很好的观点,但是sed对于这个目的非常有用。sed可以解释$prefix和$suffix的内容,这一事实可能是好的,也可能是坏的——只要您注意,就不会有问题。美妙之处在于,你可以这样做:

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

这可能是您想要的,而且比bash变量替换更漂亮、更强大。如果你记得能力越大责任越大(正如蜘蛛侠所说),你就会没事。

可以在http://evc-cit.info/cit052/sed_tutorial.html上找到sed的快速介绍

关于shell及其字符串使用的注意事项:

对于给定的特定示例,下面的代码也可以使用:

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

...但这只是因为:

Echo并不关心参数列表中有多少字符串 $前缀和$后缀中没有空格

在命令行上引用字符串通常是一种良好的实践,因为即使它包含空格,它也将作为单个参数显示给命令。我们引用$prefix和$suffix是出于同样的原因:将每个编辑命令作为一个字符串传递给sed。我们使用双引号是因为它们允许变量内插;如果我们使用单引号,sed命令将得到一个字面的$前缀和$后缀,这当然不是我们想要的。

还要注意,我在设置变量前缀和后缀时使用了单引号。我们当然不希望字符串中的任何内容被解释,所以我们对它们进行单引号,这样就不会发生插值。同样,在这个例子中可能没有必要,但这是一个很好的习惯。

其他回答

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

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

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

小而通用的解决方案:

expr "$string" : "$prefix\(.*\)$suffix"
$ prefix="hell"
$ suffix="ld"
$ string="hello-world"
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor

这在手册的Shell参数扩展部分中有记录:

${parameter#word} ${parameter##word} The word is expanded to produce a pattern and matched according to the rules described below (see Pattern Matching). If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the # case) or the longest matching pattern (the ## case) deleted. […] ${parameter%word} ${parameter%%word} The word is expanded to produce a pattern and matched according to the rules described below (see Pattern Matching). If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the % case) or the longest matching pattern (the %% case) deleted. […]

对阿德里安早餐满意:

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

像这样使用它

HELLO=":hello:"
HELLO=$(strip "$HELLO" ":")
echo $HELLO # hello

使用sed:

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

在sed命令中,^字符匹配以$前缀开头的文本,后面的$匹配以$后缀结尾的文本。

Adrian Frühwirth在下面的评论中提出了一些很好的观点,但是sed对于这个目的非常有用。sed可以解释$prefix和$suffix的内容,这一事实可能是好的,也可能是坏的——只要您注意,就不会有问题。美妙之处在于,你可以这样做:

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

这可能是您想要的,而且比bash变量替换更漂亮、更强大。如果你记得能力越大责任越大(正如蜘蛛侠所说),你就会没事。

可以在http://evc-cit.info/cit052/sed_tutorial.html上找到sed的快速介绍

关于shell及其字符串使用的注意事项:

对于给定的特定示例,下面的代码也可以使用:

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

...但这只是因为:

Echo并不关心参数列表中有多少字符串 $前缀和$后缀中没有空格

在命令行上引用字符串通常是一种良好的实践,因为即使它包含空格,它也将作为单个参数显示给命令。我们引用$prefix和$suffix是出于同样的原因:将每个编辑命令作为一个字符串传递给sed。我们使用双引号是因为它们允许变量内插;如果我们使用单引号,sed命令将得到一个字面的$前缀和$后缀,这当然不是我们想要的。

还要注意,我在设置变量前缀和后缀时使用了单引号。我们当然不希望字符串中的任何内容被解释,所以我们对它们进行单引号,这样就不会发生插值。同样,在这个例子中可能没有必要,但这是一个很好的习惯。