为什么行尾的反斜杠会放置过多的空格?

为什么行尾的反斜杠会放置过多的空格?

我想了:

#!/bin/bash
cmd --options \
    option=value,\
    option=value,\
    option=value,\
    option=value

但运行后bash -x我得到了:

cmd --options option=value, option=value, option=value, option=value

这会导致错误。

我怎样才能做到这一点,这样 bash 就不会自动放置这个空格?

答案1

嗯,每行的开头确实有空格。尽管它被压缩到一个空格中,但 bash 不会自动删除它。

为了完全避免这种情况,请将脚本编写为

#!/bin/bash
command --options \
opt1=val1,\
opt2=val2,\
opt3=val3

答案2

如果您需要将字符串opt1=val1,opt2=val2,...作为单个参数传递给命令,但希望将其放在脚本中的多行中以实现可编辑性,则可以使用数组作为中间步骤,然后在运行命令时连接所有数组元素。

例如

opts=(
    opt1=val1    # no commas here 
    opt2=val2    # but comments also work
    etc.
)
(IFS=,
 echo somecmd --options "${opts[*]}"   # echo for demonstration
)

那打印somecmd --options opt1=val1,opt2=val2,etc.

(第一对括号是数组赋值语法的一部分,第二对括号启动一个子 shell,以保护脚本的其余部分免受修改IFS。该子 shell 可能不是必需的,特别是如果脚本之后不执行任何操作,或者如果您IFS稍后重置或根本不使用它。)

显然,这需要一个功能丰富且支持数组的 shell。除了 Bash 之外,zsh 也可以。在 ksh 中,您需要引用字符串(或至少是等号),因此它不会将其变成类似结构体复合变量


如果您需要 POSIX sh 兼容的解决方案,最接近数组的等效项将是位置参数列表,但它们只有一组,并且由于set其行为或多或少类似于常规命令,因此您仍然需要记住反斜杠 (并且不能使用注释)。

相反,这样的事情应该有效:

args=$( <<EOF sed -e 's/^[[:space:]]*//' | tr '\n' ,
    opt1=val1
    opt2=val2
    etc.
EOF
)
args=${args%,}
echo somecmd --options "$args"  # echo for demonstration

答案3

另外一个选择:

#!/bin/bash
cmd --options "$(printf "%s" \
    "option=value," \
    "option=value," \
    "option=value," \
    "option=value"
)"

printf "%s"打印没有任何空格的参数,因此结果是:

cmd --options option=value,option=value,option=value,option=value

某些命令还能够完全自行删除空格,只要它作为单个参数传递即可。因此简单的引用(以防止分词)就足够了,例如ffmpeg似乎可以这样:

ffmpeg -i somefile.mp4 -vf "
    hflip,
    vflip,
    hue=s=0
" result.mp4

但这取决于您使用的命令如何处理这些选项。

还有一个选项可能会--options多次使用自身(如果您的命令允许),以防万一ffmpeg不起作用,但有时也没关系。

答案4

如果您希望能够将每个选项放在自己的行中,您可能需要尝试另一种方法:

options="opt1=val1,"
options+="opt2=val2,"
options+="opt3=val3"
your_command --options "${options}"
# note: "command" being a bash builtin, I replaced it by "your_command"
# (command foo : bypasses any alias/function "foo" and instead launches "foo" from $PATH)

相关内容