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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16623835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:43:42  来源:igfitidea点击:

Remove a fixed prefix/suffix from a string in Bash

bash

提问by Du?an Rychnovsky

In my bashscript I have a string and its prefix/suffix. I need to remove the prefix/suffix from the original string.

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

For example, let's say I have the following values:

例如,假设我有以下值:

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

How do I get to the following result?

我如何得到以下结果?

result="o-wor"

回答by Adrian Frühwirth

$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor

回答by Chris Kolodin

Using sed:

使用 sed:

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

Within the sed command, the ^character matches text beginning with $prefix, and the trailing $matches text ending with $suffix.

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

Adrian Frühwirth makes some good points in the comments below, but sedfor this purpose can be very useful. The fact that the contents of $prefix and $suffix are interpreted by sed can be either good OR bad- as long as you pay attention, you should be fine. The beauty is, you can do something like this:

Adrian Frühwirth 在下面的评论中提出了一些很好的观点,但sed为此目的可能非常有用。$prefix 和 $suffix 的内容由 sed 解释的事实可能是好的也可能是坏的 - 只要你注意,你应该没问题。美妙的是,你可以做这样的事情:

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

which may be what you want, and is both fancier and more powerful than bash variable substitution. If you remember that with great power comes great responsibility (as Spiderman says), you should be fine.

这可能是您想要的,并且比 bash 变量替换更高级、更强大。如果你记得能力越大责任越大(正如蜘蛛侠所说),你应该没问题。

A quick introduction to sed can be found at http://evc-cit.info/cit052/sed_tutorial.html

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

A note regarding the shell and its use of strings:

关于 shell 及其字符串使用的说明:

For the particular example given, the following would work as well:

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

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

...but only because:

...但只是因为:

  1. echo doesn't care how many strings are in its argument list, and
  2. There are no spaces in $prefix and $suffix
  1. echo 不关心它的参数列表中有多少个字符串,并且
  2. $prefix 和 $suffix 中没有空格

It's generally good practice to quote a string on the command line because even if it contains spaces it will be presented to the command as a single argument. We quote $prefix and $suffix for the same reason: each edit command to sed will be passed as one string. We use double quotes because they allow for variable interpolation; had we used single quotes the sed command would have gotten a literal $prefixand $suffixwhich is certainly not what we wanted.

在命令行上引用字符串通常是一种很好的做法,因为即使它包含空格,它也会作为单个参数呈现给命令。我们引用 $prefix 和 $suffix 的原因相同:每个到 sed 的编辑命令都将作为一个字符串传递。我们使用双引号是因为它们允许变量插值;如果我们使用单引号,sed 命令就会得到一个文字$prefix$suffix这肯定不是我们想要的。

Notice, too, my use of single quotes when setting the variables prefixand suffix. We certainly don't want anything in the strings to be interpreted, so we single quote them so no interpolation takes place. Again, it may not be necessary in this example but it's a very good habit to get into.

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

回答by tommy.carstensen

Do you know the length of your prefix and suffix? In your case:

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

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

Or more general:

或更一般的:

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

But the solution from Adrian Frühwirthis way cool! I didn't know about that!

但是Adrian Frühwirth解决方案非常酷!我不知道!

回答by Vladimir Petrakovich

I use grep for removing prefixes from paths (which aren't handled well by sed):

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

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

\Kremoves from the match all the characters before it.

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

回答by Vijay Vat

$ 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

Notes:

笔记:

#$prefix : adding # makes sure that substring "hell" is removed only if it is found in beginning. %$suffix : adding % makes sure that substring "ld" is removed only if it is found in end.

#$prefix : 添加 # 确保只有在开头找到的子字符串 "hell" 才会被删除。%$suffix : 添加 % 确保只有在最后找到子字符串“ld”时才会删除它。

Without these, the substrings "hell" and "ld" will get removed everywhere, even it is found in the middle.

如果没有这些,子字符串“hell”和“ld”将在任何地方被删除,即使它是在中间找到的。

回答by Martin - マーチン

Using the =~operator:

使用=~运算符

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

回答by Tosi Do

Small and universal solution:

小而通用的解决方案:

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

回答by math2001

Using @Adrian Frühwirth answer:

使用@Adrian Frühwirth 回答:

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

use it like this

像这样使用它

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

回答by Bayou

I would make use of capture groups in regex:

我会在正则表达式中使用捕获组:

$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ set +H # Disables history substitution, can be omitted in scripts.
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}//" <<< $string
o-wor
$ string1=$string$string
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}//g" <<< $string1
o-woro-wor

((?:(?!(${suffix})).)*)makes sure that the content of ${suffix}will be excluded from the capture group. In terms of example, it's the string equivalent to [^A-Z]*. Otherwise you will get:

((?:(?!(${suffix})).)*)确保 的内容${suffix}将从捕获组中排除。就示例而言,它是等效于[^A-Z]*. 否则你会得到:

$ perl -pe "s/${prefix}(.*)${suffix}//g" <<< $string1
o-worldhello-wor