如何在Bash脚本中迭代参数

时间:2008-11-01 18:14:22

标签: bash command-line

我有一个复杂的命令,我想制作一个shell / bash脚本。我可以用$1轻松地写出来:

foo $1 args -o $1.ext

我希望能够将多个输入名称传递给脚本。什么是正确的方法呢?

当然,我想处理其中包含空格的文件名。

9 个答案:

答案 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