我有一个复杂的命令,我想制作一个shell / bash脚本。我可以用$1
轻松地写出来:
foo $1 args -o $1.ext
我希望能够将多个输入名称传递给脚本。什么是正确的方法呢?
当然,我想处理其中包含空格的文件名。
答案 0 :(得分:1275)
使用"$@"
表示所有参数:
for var in "$@"
do
echo "$var"
done
这将迭代每个参数并在单独的行上打印出来。 $ @的行为类似于$ *,但是当引用时,如果参数中存在空格,则正确地将其分解:
sh test.sh 1 2 '3 4'
1
2
3 4
答案 1 :(得分:217)
答案 2 :(得分:115)
请注意,罗伯特的答案是正确的,它也适用于sh
。您可以(便携地)进一步简化它:
for i in "$@"
相当于:
for i
即,你什么都不需要!
测试($
是命令提示符):
$ set a b "spaces here" d
$ for i; do echo "$i"; done
a
b
spaces here
d
$ for i in "$@"; do echo "$i"; done
a
b
spaces here
d
我首先在Kernighan和Pike的 Unix Programming Environment 中读到过这个。
在bash
中,help for
记录了这一点:
for NAME [in WORDS ... ;] do COMMANDS; done
如果
'in WORDS ...;'
不存在,则假定为'in "$@"'
。
答案 3 :(得分:52)
对于简单的情况,您也可以使用shift
。
它将参数列表视为队列,每个shift
抛出第一个参数,
剩下的每个参数的数量都会递减。
#this prints all arguments
while test $# -gt 0
do
echo $1
shift
done
答案 4 :(得分:12)
您也可以将它们作为数组元素访问,例如,如果您不想遍历所有这些元素
argc=$#
argv=($@)
for (( j=0; j<argc; j++ )); do
echo ${argv[j]}
done
答案 5 :(得分:3)
aparse() {
while [[ $# > 0 ]] ; do
case "$1" in
--arg1)
varg1=${2}
shift
;;
--arg2)
varg2=true
;;
esac
shift
done
}
aparse "$@"
答案 6 :(得分:2)
扩大baz的答案,如果您需要使用索引枚举参数列表(例如搜索特定单词),则可以执行此操作而无需复制列表或对其进行变异。
假设您要在双破折号(“-”)处分割参数列表,并将破折号前的参数传递给一个命令,并将破折号后的参数传递给另一个命令:
toolwrapper() {
for i in $(seq 1 $#); do
[[ "${!i}" == "--" ]] && break
done || return $? # returns error status if we don't "break"
echo "dashes at $i"
echo "Before dashes: ${@:1:i-1}"
echo "After dashes: ${@:i+1:$#}"
}
结果应如下所示:
$ toolwrapper args for first tool -- and these are for the second
dashes at 5
Before dashes: args for first tool
After dashes: and these are for the second
答案 7 :(得分:1)
getopt 在脚本中使用命令来格式化任何命令行选项,或者 参数。
#!/bin/bash
# Extract command line options & values with getopt
#
set -- $(getopt -q ab:cd "$@")
#
echo
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) param="$2"
echo "Found the -b option, with parameter value $param"
shift ;;
-c) echo "Found the -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option";;
esac
shift
答案 8 :(得分:1)
对 $# 进行循环,参数变量的数量也有效。
#! /bin/bash
for ((i=1; i<=$#; i++))
do
printf "${!i}\n"
done
test.sh 1 2 '3 4'
输出:
1
2
3 4