【问题标题】:Add all arguments except first to a string将除 first 之外的所有参数添加到字符串
【发布时间】:2015-12-17 21:03:12
【问题描述】:

试图将所有参数解析为一个字符串,但我的代码只给我它找不到 i 的错误:

test: line 3: =: command not found
test: line 7: [i: command not found
test: line 7: [i: command not found
test: line 7: [i: command not found
test: line 7: [i: command not found
test: line 7: [i: command not found

代码如下

#!/bin/sh

$msg=""

for i in $@
do
if [i -gt 1]; then
    msg="$msg $i"
fi
done

编辑:感谢所有的帮助,让它工作。如果有人感兴趣,我的最终解决方案:

#!/bin/sh

args=""
for i in "${@:2}"
do
    args="$args $i"
done

【问题讨论】:

  • 第一个错误(test: line 3: =: command not found)来自msg的赋值错误:将第3行替换为msg=""(不是美元,这是shell,不是Perl或PHP)。

标签: string bash sh args


【解决方案1】:

[ 只是(或多或少)test 的别名,因此您应该像使用常规命令一样使用它。我想说的是,[ 前后都需要空格,如下所示:

if [ $i -gt 1 ]; then

您还忘记了if 子句中i 之前的$

【讨论】:

  • 在使用[] 时应该真正引用变量,或者只使用[[]],因为它是bash。
  • 看起来您正在尝试使用 $i 作为命令参数的索引。那是行不通的。 $i 是实际参数本身。使用shift 丢弃第一个参数并将所有其他参数向左移动一个位置。然后你可以做 `msg="$@"
  • 我认为 OP 也不知道如何分配变量。关于$msg="" :)
  • 5 分钟内我没有在 sh 中乱写代码 :) 现在可以工作了,谢谢
  • @Prototype 来自 bash 手册页:可以通过以下形式的语句为变量赋值: name=[value]。所以分配变量应该没有美元。 ;)
【解决方案2】:

显示您的特定错误消息是因为:

  • 分配变量不是用$ 字符来完成的,就像$msg="" 一样,你应该使用msg="";和

  • [ 实际上是一个命令, 应该用空格与其他单词隔开,这样shell 就不会认为你在尝试执行一些神话般的@ 987654325@命令。

但是,您还有其他一些问题。首先是i的值需要用$i获取,而不仅仅是i。单独使用 i 会给你一个错误:

-bash: [: i: integer expression expected

因为i 本身不是数值。

其次,i$i 都不会是您可以与 1 进行比较的 index,因此您的 $i -gt 1 表达式将不起作用。单词$i 将扩展为参数的,而不是它的索引。


但是,如果您真的想处理参数列表中除第一个元素之外的所有元素,bash 有一些非常类似于 C 的结构,这将使您的生活更轻松:

for ((i = 2; i <= $#; i++)) ; do   # From two to argc inclusive.
    echo Processing ${!i}
done

使用参数hello my name is pax 运行它会导致:

Processing my
Processing name
Processing is
Processing pax

要构造一个包含这些参数的字符串,你可以使用类似的东西:

msg="$2"                           # Second arg (or blank if none).
for ((i = 3; i <= $#; i++)) ; do   # Append all other args.
    msg="$msg ${!i}"
done

这会给你(与上述相同的论点):

[my name is pax]

尽管在这种情况下,有一种更简单的方法,根本不涉及任何(显式)循环:

msg="${@:2}"

【讨论】:

  • 如果您使用的是 bash,那么为什么要使用 eval echo \$$i 而不是 ${!i}
  • @999999999999999999999999999999:因为到现在为止,我从来不知道那个,总是用eval作为间接的。更改了答案以使用这种“新”方法,这也应该使我的代码更加清晰:-) 干杯。
  • 虽然我们在这里:如果您只想连接所有参数(不包括第一个参数),您不妨放弃所有这些并使用此参数扩展:@987654346 @.
【解决方案3】:

您实际上并不需要针对特定​​输出的循环(假设单个字符串实际上是正确的输出):

args="${@:2}"  # Use @ instead of * to avoid IFS-based surprises

但是,如果您打算稍后对参数进行迭代,那么扁平字符串是错误的方法。您应该使用数组:

args=( "${@:2}" )

【讨论】:

  • 请注意,如果 IFS 已更改,args=${*:2} 可能会令人惊讶……args="${@:2}"(带引号)应该不会那么令人惊讶。
  • 好点;这是我认为引用 $@ 和不引用它之间没有区别的一种情况。
  • 在 4.3.11(1)-release 上,f() { local IFS=; a=${@:2}; echo "$a"; }; f a b c d 产生 bcd,而 f() { local IFS=; a="${@:2}"; echo "$a"; }; f a b c d 产生 b c d(如预期)...
猜你喜欢
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
相关资源
最近更新 更多