删除变量前后的子字符串

删除变量前后的子字符串

我知道我可以从变量前面删除子字符串:

X=foobarbaz
echo ${X#foo}       # barbaz

...以及从变量的后面:

echo ${X%baz}       # foobar

我如何将两者结合起来?我试过了:

echo ${{X#foo}%baz}    # "bad substitution"
echo ${${X#foo}%baz}   # "bad substitution"
echo ${X#foo%baz}      # foobarbaz

我不思考我可以使用中间变量,因为它在 中使用find -exec,如下所示:

find ./Source -name '*.src' \
    -exec bash -c 'myconvert -i "{}" -o "./Dest/${0#./Source/%.src}.dst"' {} \;

答案1

我认为这是不可能的(但很想被证明是错误的)。但是,您可以使用中间变量。与其他实例一样,运行bash -c-exec只是一个 bash 实例:

$ find . -type f
./foobarbaz
$ find . -type f -exec bash -c 'v=${0#./foo}; echo ${v%baz}'  {} \;
bar

所以我看不出为什么这行不通(如果我理解你想要正确做的事情):

find ./Source -name '*.src' \
     -exec bash -c 'v=${0%.src}; \ 
        myconvert -i "{}" -o "./Dest/${v#./Source/}.dst"' {} \;

答案2

通常的方法是分两步进行:

x=foobarbaz
y=${x#foo}       # barbaz
z=${y%baz}       # bar

由于这是“参数扩展”,因此需要“参数”(变量)才能执行任何替换。这意味着需要 y 和 z。即使它们可能是相同的变量:

x=foobarbaz
x=${x#foo}       # barbaz
x=${x%baz}       # bar

find ./Source/ -name '*.src' -exec \
    bash -c '
        x=${1#./Source/}
        myconvert -i "$1" -o "./Dest/${x%.src}.dst"
    ' shname {} \;

其中shname是参数$0,下一个{}$1bash 调用的参数。


cd ./Source一个更简单的选择是在开始时执行 a以避免稍后删除该部分。就像是:

cd ./Source                 ### Maybe test that it exist before cd to it.
shopt -s extglob nullglob   ### Make sure that correct options are set.

for f in *.src **/*.src; do
    echo \
    myconvert -i "$f" -o "./Dest/${f%.src}.dst"
done

一旦您确信它符合您的要求,请注释掉回声。

答案3

我总是一步一步地做:

X=foobarbaz; X="${X#foo}"; X="${X%baz}"

答案4

我很惊讶这还没有被建议,但是 Bash子串扩展会为你做这件事的。如果前缀和后缀的长度已知,您可以简单地执行以下操作:

X=foobarbaz
echo ${X:3:-3}
# output: bar

如果前缀和后缀是变量,则必须使用 POSIX 标准字符串长度扩展获取偏移量:

X=foobarbaz
prefix=fo
suffix=az
echo ${X:${#prefix}:-${#suffix}}
# output: obarb

相关内容