【发布时间】:2023-03-12 12:26:01
【问题描述】:
我正在编写一个 bash 脚本,它需要遍历传递给脚本的参数。但是,第一个参数不应该被循环,而是需要在循环之前进行检查。
如果我不必删除第一个元素,我可以这样做:
for item in "$@" ; do
#process item
done
我可以修改循环以检查它是否在第一次迭代中并更改行为,但这似乎太老套了。必须有一种简单的方法来提取第一个参数,然后遍历其余参数,但我找不到它。
【问题讨论】:
我正在编写一个 bash 脚本,它需要遍历传递给脚本的参数。但是,第一个参数不应该被循环,而是需要在循环之前进行检查。
如果我不必删除第一个元素,我可以这样做:
for item in "$@" ; do
#process item
done
我可以修改循环以检查它是否在第一次迭代中并更改行为,但这似乎太老套了。必须有一种简单的方法来提取第一个参数,然后遍历其余参数,但我找不到它。
【问题讨论】:
使用shift?
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html
基本上,为循环前的第一个参数读取$1(或$0,如果您要检查的是脚本名称),然后使用shift,然后循环剩余的$@。
【讨论】:
另一种变体使用数组切片:
for item in "${@:2}"
do
process "$item"
done
如果由于某种原因您想保留参数,这可能很有用,因为 shift 具有破坏性。
【讨论】:
"${!1}${@:2}" 中的第一个参数
firstitem=$1
shift;
for item in "$@" ; do
#process item
done
【讨论】:
$0一般是脚本名。
in "$@" 部分是隐含的,可以省略。
set -- 1 'two' 'three four'; for item; do echo "[$item]"; done
q=${@:0:1};[ ${2} ] && set ${@:2} || set ""; echo $q
编辑
> q=${@:1}
# gives the first element of the special parameter array ${@}; but ${@} is unusual in that it contains (? file name or something ) and you must use an offset of 1;
> [ ${2} ]
# checks that ${2} exists ; again ${@} offset by 1
> &&
# are elements left in ${@}
> set ${@:2}
# sets parameter value to ${@} offset by 1
> ||
#or are not elements left in ${@}
> set "";
# sets parameter value to nothing
> echo $q
# contains the popped element
一个带有规则数组的pop示例
LIST=( one two three )
ELEMENT=( ${LIST[@]:0:1} );LIST=( "${LIST[@]:1}" )
echo $ELEMENT
【讨论】:
q=${@:0:1} (顺便说一句,您的解释错误地将其引用为q=${@:1})应该是q=${@:1:1} 更清楚:$@ 以索引 1 开头,大概是并行的显式 $1, $2, ... 参数 - 元素 0 具有 no 值(与其显式对应物 $0 不同,它反映了 shell / 脚本文件)。 [ ${2} ] 将 break 应该 $2 包含嵌入的空格;如果您改用[[ ${2} ]],就不会遇到这个问题。也就是说,不需要条件和 || 分支:如果只有 1 个参数,${@:2} 将简单地扩展为空字符串(续)。
set -- 以确保恰好看起来像选项的参数不会被 set 解释为这样,并且您应该双引号${@:2} 引用和$q 引用在echo 语句中。此时我们得到:q=${@:1:1}; set -- "${@:2}"; echo "$q"。然而,q=${@:1:1} 只是另一种(更繁琐的)表达$1 的方式,其余的基本上重新实现了shift 命令;使用这些功能我们很容易得到:q=$1; shift; echo "$q".