如何有条件地从 POSIX shell 脚本传递参数?

Sha*_*oon 19 shell-script posix arguments

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"
for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise $1 --snr 25 --iterations 1250 --enhancement $2
done
Run Code Online (Sandbox Code Playgroud)

如果$2未指定,我不想将--enhancement $2参数传递给我的 python 脚本。我该怎么做?

Kus*_*nda 31

修改您的原始脚本:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"
for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise "$1" --snr "$snr" --iterations 1250 ${2:+--enhancement "$2"}
done
Run Code Online (Sandbox Code Playgroud)

如果变量已设置且不为空${var:+word}word标准参数扩展将扩展为var。在上面的代码中,我们使用它来添加--enhancement "$2"命令 if$2可用且不为空。

我还冒昧地假设您提供--snr的选项参数应该是循环变量的值。


我个人对代码的接触(主要是使用printf而不是echo,避免长行,并给代码更多的空气):

#!/bin/sh

printf 'Noise %s\n' "$1"
printf 'Enhancement %s\n' "$2"

for snr in 0 5 10 15 20 25; do
    python evaluate.py \
        --noise "$1" \
        --snr "$snr" \
        --iterations 1250 \
        ${2:+--enhancement "$2"}
done
Run Code Online (Sandbox Code Playgroud)

正如 mosvy 在下面的评论中指出的那样:如果您/bin/sh碰巧是dashshell,或者IFS在新的 shell 会话开始时没有正确重置的其他 shell (POSIX 要求这样做),并且如果您有,出于某种原因,导出IFS并给它一个非默认值,那么您可能希望unset IFS在上述脚本的顶部使用。

每当您解决了出口IFS无疑引起的所有其他问题(不要出口IFS)时,请执行此操作。


Ini*_*ian 12

在不支持任何数组的最小 POSIX shell 上,您可以使用set命令操作位置参数列表。就在for你可以做的循环之前

if [ -z "$2" ]; then
    set -- --noise "$1" --snr 25 --iterations 1250
else
    set -- --noise "$1" --snr 25 --iterations 1250 --enhancement "$2"
fi
Run Code Online (Sandbox Code Playgroud)

现在运行你的 for 循环

for snr in 0 5 10 15 20 25; do
    python evaluate.py "$@"
done
Run Code Online (Sandbox Code Playgroud)

如果你的外壳支持阵列伯恩再次壳bashzsh或者其他,你可以使用数组

argv=(--noise "$1" --snr 25 --iterations 1250)

if [ ! -z "$2" ]; then
    argv+=( --enhancement "$2" )
fi
Run Code Online (Sandbox Code Playgroud)

现在将脚本称为

python evaluate.py "${argv[@]}"
Run Code Online (Sandbox Code Playgroud)

正如评论中所指出的,您没有使用snrfor 循环中value的实际值。使用$snr脚本参数中适用的值,在这种情况下,您可能需要在循环内移动构建参数列表的逻辑。