将命令行参数转换为Bash中的数组


160

如何将命令行参数转换为bash脚本数组?

我要这样:

./something.sh arg1 arg2 arg3

并将其转换为

myArray=( arg1 arg2 arg3 )

这样我就可以在脚本中使用myArray进行进一步使用。

上一则SO文章即将结束,但没有涉及如何创建数组:如何在Bash中解析命令行参数?

我需要将参数转换为常规的bash脚本数组;我意识到我可以使用其他语言(例如Python),但是需要在bash中执行此操作。我猜我在寻找“附加”功能或类似的东西?

更新:我还想问一下如何检查零个参数并分配一个默认的数组值,并且由于下面的答案,所以能够使它工作:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

Answers:


206

实际上,您的命令行参数实际上已经像一个数组。至少,您可以$@像对待数组一样对待变量。也就是说,您可以将其转换为实际的数组,如下所示:

myArray=( "$@" )

如果只想输入一些参数并将其输入$@值,请使用set

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

理解如何使用参数结构在POSIX sh中特别有用,因为POSIX sh没有其他东西像数组。


2
谢谢!很棒!刚要问如何检查零个参数并分配一个默认的数组值,而$#可以完美地做到这一点!
苏曼(Suman)2012年

1
set允许您设置示波器的位置参数。它还允许您设置外壳选项。您可以这样做set foo,这意味着$1将扩展为“ foo”,但是如果您的参数以破折号开头,set则会假设您要设置一个shell选项。双破折号确保将以下所有参数解释为要设置的位置参数。
kojiro 2014年

11
一个陷阱:echo $@将显示所有参数,但echo $myArray仅显示第一个元素。要查看所有内容,请使用echo ${myArray[@]}
z0r 2015年

4
@ z0r如果您不在这些扩展名两边加上双引号,则bash会对其重新进行单词拆分,并可能失去意义。
kojiro 2015年

正确,“散布”数组并使用每个元素的一般方法是"${myArray[@]}"。如果要遍历数组,则需要使用引号避免在IFS上拆分其单个元素
BallpointBen

66

也许这可以帮助:

myArray=("$@") 

您也可以通过省略“ in”来遍历参数:

for arg; do
   echo "$arg"
done

将等效

for arg in "${myArray[@]}"; do
   echo "$arg"
done

3
新手问题:bash如何知道要放入arg字段的内容-它是预定义的变量吗?${var}扩展到的内容var${var[n]}扩展为narray 元素的内容var。被${var[@]}然后扩展整个阵列,即${var[0]} ${var[1]} ... ${var[n]}(带n是最后一个元素的索引)?
基督徒

4
不带[in]的[for]将循环遍历参数数组$ @($ 1,$ 2等)。也可以使用[set]命令进行设置,例如set-arg1 arg2
Nahuel Fouilleul

17

实际上,可以使用$1 $2 ...etc 来访问参数列表。
这完全等同于:

${!i}

因此,参数列表可以用一组被改变,
并且${!i}是访问它们的正确方法:

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

对于您的特定情况,可以在不需要给出任何参数的情况下使用它(无需数组)来设置参数列表:

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

转化为更简单的表达:

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

回声示例不应该是:echo "$#" "$i+1" "${!i}";完全按照所示获得输出吗?
Zael

6

这是另一种用法:

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

4

更容易,但是您可以直接在$@;)上操作

这是直接从提示符传递args列表的方法:

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

1
甚至更简单,for stuff in "$@" ; do ...for stuff ; do ...:) 相同
kkm

1

数组和$ @几乎相同的并排视图。

码:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

输入:

./bash-array-practice.sh 1 2 3 4

输出:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4

1

双引号的重要性值得强调。假设参数包含空格。

码:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

输出:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.