我如何能够在 shell 脚本中使用 $14 访问第 14 个位置参数?

Col*_*ack 42 shell-script

我正在阅读 Unix 中的位置参数,然后我找到了这个信息:

shell 允许一个命令行包含至少 128 个参数;然而,shell 程序仅限于在给定时间仅引用 9 个位置参数,即 $1 到 $9。您可以使用 shift 命令解决此限制。

所以我创建了一个简单的 shell 脚本file,如下所示:

#! /bin/bash
echo $14
Run Code Online (Sandbox Code Playgroud)

然后像下面这样运行它:

./file 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Run Code Online (Sandbox Code Playgroud)

我得到了 14 个!

那么,如果 shell 在不使用shift命令的情况下不允许超过 10 个参数(从 $0 到 $9),那怎么可能呢?

小智 69

当你跑

echo $14
Run Code Online (Sandbox Code Playgroud)

发生的事情是 bash 将参数解释$14$14分开。然后它展开$1(在这种情况下等于“1”),然后将字符串附加4到它,结果是“14”。尽管这是您期望的结果,但它实际上是 Bash 实际行为的副作用。就像评论中提到的@steeldriver 一样,像这样运行你的脚本:

./file a b c d e f g h i j k l m n
Run Code Online (Sandbox Code Playgroud)

然后调用echo $14不会输出“n”而是“a4”。

请注意,将变量用双引号括起来:

echo "$14"
Run Code Online (Sandbox Code Playgroud)

仍然不会在 Bash 中正确扩展变量。标准方法是在变量名周围使用花括号:

echo ${14}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅Bash 中参数扩展的官方文档。它也可以做很多很酷的事情,比如

${14^^*}
Run Code Online (Sandbox Code Playgroud)

大写第 14 号论点。给它一个阅读!:)

  • 请注意,在 csh、ash、tcsh、rc、es、akanga 和 zsh(当不是在 sh/ksh 仿真中),虽然在一些 ash 衍生物中再次被打破以符合 POSIX。 (9认同)
  • @ilkkachu、*fixed* 或 *broken* 取决于您想如何看待它。根据我在这里的第一条评论,它曾经很好,但在较新的版本中被*破坏*(IMO)以符合 POSIX 标准。 (4认同)
  • 如果这对你有用,那是因为你使用了 `dash`(Debian 的 `/bin/sh`),其中简单的 `echo $14` 也可以:`dash -c 'echo $14' - abcdefghijklmn` => `n `. (3认同)
  • 仅将变量用双引号括起来是行不通的:`bash -c 'echo "$14"' - WTF` => `WTF4`。 (2认同)
  • @StéphaneChazelas,好吧。据我了解,Dash 旨在按原样实现 POSIX shell 语言,而不是创建一种新的但实际上理智的语言。因此,在这种情况下,与几乎所有其他类似 POSIX 的 shell 既不合规又不同的行为无疑是一个错误。 (2认同)