【问题标题】:cant create third parameter in bash script (after $*)无法在 bash 脚本中创建第三个参数(在 $* 之后)
【发布时间】:2017-06-09 13:49:31
【问题描述】:

我想创建一个 bash 脚本,它有 3 个参数。但第二个必须是$*,因为我稍后需要这些行。其他两个参数(第一个和第三个)不需要这个。

for x in $* do

第一个和第二个参数没有问题,这个有效:

parameter1="$1"
shift
parameter2="$*"

但我需要最后的第三个参数和类似的东西

parameter1="$1"
parameter3="$3"
shift
parameter2="$*"

行不通。我最后的命令应该是这样的:

bash myscript parameter1 parameter2 parameter3

【问题讨论】:

  • 你的意思是要第一个参数和最后一个参数,然后遍历中间的所有参数吗?
  • $*,就其本质而言,将所有剩余的参数捕获到一个字符串中。 全部
  • (这也意味着你失去了"one arg" "another arg"one arg another arg"one arg another arg"之间的区别——一般来说,$*的效果是不受欢迎的,你不应该把它用作你在这里)。
  • ...也就是说:for x in $* 基本上总是错的。 for x in "$@" 是正确的选择。
  • 顺便说一句,我不确定这里是否有足够的上下文来解释为什么您认为您需要$*"$@"。而不是myscript parameter1 parameter2 parameter3,为什么不用myscript parameter1 "parameter2" parameter3,而第二个使用"$2"

标签: linux bash parameters


【解决方案1】:

shift 从左边删除一个参数。如果你想从 right 中删除一个参数,你可以这样做:

set -- "${@:1:$# - 1}"

因此:

parameter1=$1          # capture leftmost argument
shift                  # remove leftmost argument

parameter3=${*:$#:1}   # capture rightmost argument
set -- "${@:1:$# - 1}" # remove rightmost argument

parameter2=$*          # concatenate remaining arguments and store in a string

请注意,$* 几乎可以肯定是错误的。如果你想保持你的论点分开,尊重他们的引用,而不是使用一个数组:

parameter2=( "$@" )
for item in "${parameter2[@]}"; do
  echo "Processing item: $item"
done

如果您的脚本以yourscript arg1 "item A" "item B" arg3 运行,那么以上将确保item Aitem B 被视为单独的参数,而不是将item 作为一个参数,A 作为另一个参数,等等。

【讨论】:

  • 抱歉,“从左到右”或“从左到右”是什么意思?你的意思是,$* 忽略左边的参数?
  • @ipo,我的意思是 shift 将旧的 $1 从参数列表中完全删除,并使 $2 成为 $1$3 成为$2$4$3 等。如果在你运行 shift 之前,$1one$2two,那么 之后 shift,然后$1two,而one消失了
  • @ipo, ...并且要清楚,这就是它始终的作用;这不是某种神奇的“删除我刚刚阅读的内容”操作;相反,它将参数列表左侧的内容移出,然后移动这些内容右侧的内容以填充空出的位置。
  • 相比之下,@ipo, ...$* 采用 整个参数列表 并将其塞进一个字符串中,其中包含 IFS 变量的第一个字符(由默认,一个空格)在这些参数之间注入。如果您使用shift 将某些内容从参数列表中取出,那么该内容将不再包含在"$*" 中。
  • @ipo, ...所以,你可以试试这个:set -- one two three; echo $1; shift; echo $1——你会看到第一个echo发出one,第二个发出two,因为$1 在调用shift 时发生了变化。您可以将$1s 替换为$*s 以查看那里的影响。
【解决方案2】:

对于具体的三个参数,可以简单的使用子串参数扩展:

parameter1=$1
parameter2="${@:2:1}"   # One parameter, starting with #2
parameter3=$3

当然,这是不必要的,因为您可以只使用 $2 而不是 ${@:2:1},但我指出它只是对语法的简单介绍(根本不是因为我忽略了您会使用 @987654324 的事实@,真的……)

(也可以用它来代替间接参数扩展;"${@:n:1}""${!n}"n是整数值的变量时基本等价。)

对于更一般的情况,您希望在第一个和最后一个之间有任意数量的参数,它会变得有点复杂,尽管原理是相同的:

parameter1=$1
middleParameters=( "${@:2:$#-2}" )  # n - 2 parameters, starting with #2, i.e., all but $1 and ${!n} for n=$#
lastParameter="${@:$#}"

【讨论】:

  • 你确定 "${@:n:1}" 和 "${!n}" 基本上是等价的吗?我尝试:设置 A B C ;乙=99; echo "${@:2:1}" ; echo "${!2}",第一行得到“B”,第二行得到 99。我理解错了吗?
  • 我应该更明确一点;我的意思是一个 literal 变量n 具有一个整数值来表示该等价。 (我说“基本上”是因为我也没有费心检查每种情况下诸如越界索引之类的其他差异。)
  • 好的,我测试过,我发现它有效。所以,如果我理解正确的话,如果扩展中使用的起始索引是一个字面整数,则按原样使用,但如果是变量名,则扩展为该变量的值。我说的对吗?
  • 对;索引是在算术上下文中评估的,就像您改写了 ${@:$((n)):1} 一样。
猜你喜欢
  • 2020-06-27
  • 2012-10-07
  • 2019-03-20
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 2022-07-02
相关资源
最近更新 更多