我正在编写一段bash脚本,需要循环遍历传递到脚本中的参数。然而,第一个参数不应该被循环遍历,而是在循环之前需要进行检查。
如果我不需要删除第一个元素,我只需执行以下操作:
for item in "$@" ; do
#process item
done
我可以修改循环以检查它是否处于第一次迭代并更改行为,但那似乎太过hackish。肯定有一种简单的方法可以提取第一个参数,然后循环遍历其余部分,但我找不到。
使用 shift
。
在循环之前,先阅读第一个参数 $1
(如果你想要检查的是脚本名称,则为 $0
),然后使用 shift
,接着遍历剩余的 $@
。
echo "$@"; # will echo all args
shift; # will remove first arg from the "$@"
echo "$@"; # will echo all args except first one
for item in "${@:2}"
do
process "$item"
done
如果出于某种原因您想保留参数而不对其进行更改,那么这可能是有用的,因为shift
是破坏性的。
"${!1}${@:2}"
中不需要临时变量来解除引用第一个参数。 - Charlie Gorichanazshift
是破坏性的人:它实际上从参数列表中最终删除了该元素。参考:https://unix.stackexchange.com/a/174568/254204 - pico_probfirstitem=$1
shift;
for item in "$@" ; do
#process item
done
$0
通常是脚本名称。 - Amberset -- 1 'two' 'three four'; for item; do echo "[$item]"; done
- mklement0q=${@: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 没有值(不像它的显式对应 $0
,它反映了 shell / 脚本文件)。如果 $2
包含嵌入空格,则 [ ${2} ]
将 _中断_;如果使用 [[ ${2} ]]
,则不会出现此问题。话虽如此,条件和 ||
分支是不必要的:如果只有一个参数,则 ${@:2}
将简单地扩展为空字符串(续)。 - mklement0set --
来确保看起来像选项的参数不会被 set
解释,并且在 echo
语句中应该对 ${@:2}
引用和 $q
引用加上双引号。此时我们得到:q=${@:1:1}; set -- "${@:2}"; echo "$q"
。但是,q=${@:1:1}
只是另一种(更繁琐的)方式来表示 $1
,其余部分本质上重新实现了 shift
命令;使用这些特性,我们只需输入:q=$1; shift; echo "$q"
。 - mklement0