删除变量前后的子串

Rog*_*mbe 12 bash string

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

X=foobarbaz
echo ${X#foo}       # barbaz
Run Code Online (Sandbox Code Playgroud)

...从变量的后面:

echo ${X%baz}       # foobar
Run Code Online (Sandbox Code Playgroud)

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

echo ${{X#foo}%baz}    # "bad substitution"
echo ${${X#foo}%baz}   # "bad substitution"
echo ${X#foo%baz}      # foobarbaz
Run Code Online (Sandbox Code Playgroud)

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

find ./Source -name '*.src' \
    -exec bash -c 'myconvert -i "{}" -o "./Dest/${0#./Source/%.src}.dst"' {} \;
Run Code Online (Sandbox Code Playgroud)

ter*_*don 7

我认为这是不可能的(但很想被证明是错误的)。但是,您可以使用中间变量。在bash -c通过运行-exec仅仅是一个bash的实例,就像任何其他:

$ find . -type f
./foobarbaz
$ find . -type f -exec bash -c 'v=${0#./foo}; echo ${v%baz}'  {} \;
bar
Run Code Online (Sandbox Code Playgroud)

所以我看不出为什么这不起作用(如果我理解你正在尝试正确做的事情):

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


小智 7

通常的方法是分两步完成:

x=foobarbaz
y=${x#foo}       # barbaz
z=${y%baz}       # bar
Run Code Online (Sandbox Code Playgroud)

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

x=foobarbaz
x=${x#foo}       # barbaz
x=${x%baz}       # bar
Run Code Online (Sandbox Code Playgroud)
find ./Source/ -name '*.src' -exec \
    bash -c '
        x=${1#./Source/}
        myconvert -i "$1" -o "./Dest/${x%.src}.dst"
    ' shname {} \;
Run Code Online (Sandbox Code Playgroud)

哪里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
Run Code Online (Sandbox Code Playgroud)

一旦您确信它可以满足您的要求,请注释掉回声。