我正在编写一个 shell 脚本,我需要打印脚本的第 n 个参数。
例如,假设我们有n=3
并且我们的脚本使用足够的参数运行。现在我需要打印第n
th 个参数,即$3
。
但如果n=2
,我们会打印参数$2
。
我不想使用if
语句。我想做类似的事情
echo $($n)
但上面的方法并没有按照我需要的方式工作。
答案1
按时间顺序,在各种 shell 中:
- csh(70 年代末):(
$argv[$n]
自 1991 年以来也适用于 zsh,自 2005 年以来也适用于 Fish) - zsh (1991):
$argv[n]
// (最后一个也被 yash 支持,但只有额外的大括号$@[n]
: / )$*[n]
${@[n]}
${*[n]}
- rc (90 年代初):
$$n
/$*($n)
(也适用于 es、akanga) - ksh93 (1993):
${@:n:1}
,${*:n:1}
(自 1996 年以来 bash 也支持;zsh 也自2010年以来,尽管您需要${@:$n:1}
或${@: n:1}
避免与 csh 样式修饰符发生冲突并查看那里关于"$*"
案件) - 巴什(1996):
${!n}
- 兹什(1999年):
${(P)n}
.
请记住,在 ksh93/bash/yash 中,您至少需要在列表上下文中引用参数扩展,而 csh 很难用来编写可靠的代码。
在 中,当第 n个位置参数未设置时,列表上下文中和bash
之间存在差异,因为后者扩展为根本没有参数,而前者扩展为一个空元素。"${!n}"
"${@:n:1}"
在类似 Bourne 的 shell 中(但不是 Bourne shell,因为它不适用于第 9 个以上的索引),并且使用标准 POSIX sh 语法,您还可以执行以下操作:
eval "nth=\${$n}"
如果不包含严格大于 0 的整数的规范十进制表示,那么所有这些之间的行为也会有所不同。$n
如果您不能保证会出现这种情况,那么使用其中的大多数(而不仅仅是一个eval
)会引入任意命令执行漏洞(唯一的例外是 withrc
和 可能是csh
上面的)。
还要记住,除了zsh
(with echo -E - $argv[n]
)、yash
(with ECHO_STYLE=raw echo "${*[$n]}"
) 和fish
(with echo -- $argv[$n]
) 之外,echo
不能用于输出任意数据,请printf '%s\n' ...
改为使用)。
答案2
您传递给脚本的参数存储在数组中@
,因此执行您想要的操作的简单方法是采用数组切片,从位置开始n
,长度为 1:
#!/bin/bash
n=3
echo "Argument $n: ${@:n:1}"
如果您使用一些参数运行此命令,您将得到:
$ foo.sh a b c d e f
Argument 3: c
另一种选择,也就是您最初要求的,称为“间接扩展”:
#!/bin/bash
n=3
echo "Argument $n: ${!n}"
运行这个:
$ foo.sh a b c d e f
Argument 3: c
答案3
您可以使用变量间接:
#!/bin/bash
n=3
echo "${!n}"
答案4
简单的便携式 shell(无 bash 依赖性)解决方案(对命令的潜在缺陷取模echo
;它可以替换为printf
):
print_nth () {
shift "$1"
echo "$1"
}
然后做:
print_nth "$n" "$@"