下面的示例代码演示了可以使用单行printf命令轻松检查arglist /参数,而不能使用同一命令检查根据参数创建的数组。它提醒我们,如果任何参数碰巧包含空格,则“变量”方法将失去各个参数之间的区别。
是否有一种方法可以将脚本的arglist复制到新对象,可以使用此单行printf命令对其进行检查?
脚本的参数列表在结构和行为上是否与可以在bash脚本中创建的任何对象(类似于数组,变量等)相同?
#!/bin/bash
# Only for demonstration purposes, override all arguments.
set -- 'The dog ate the "mouse" ' but the cat?
# Create an array from script arguments.
declare -a argarray=( "$@" )
# Create a variable from script arguments.
argvariable="$@"
# Various ways of trying to inspect script arguments.
printf 'arguments:%s\n' "$@"
declare -p @
printf 'arguments, loop:\n'
countargs="0"
for x in "${@}"
do
countargs=$(printf '%s\n' "1+$countargs" | bc)
printf '%s\n' "$countargs: '$x'"
done
printf '\n'
# Various ways of trying to inspect argarray.
printf 'argarray:%s\n' "$argarray"
declare -p argarray
printf 'argarray, loop:\n'
countargs="0"
for x in "${argarray[@]}"
do
countargs=$(printf '%s\n' "1+$countargs" | bc)
printf '%s\n' "$countargs: '$x'"
done
printf '\n'
# Various ways of trying to inspect argvariable.
printf '\n'
printf 'argvariable:%s\n' "$argvariable"
declare -p argvariable
printf 'argvariable in curly brackets, loop:\n'
countargs="0"
for x in "${argvariable[@]}"
do
countargs=$(printf '%s\n' "1+$countargs" | bc)
printf '%s\n' "$countargs: '$x'"
done
printf 'argvariable not bracketed, loop:\n'
countargs="0"
for x in $argvariable
do
countargs=$(printf '%s\n' "1+$countargs" | bc)
printf '%s\n' "$countargs: '$x'"
done
答案 0 :(得分:1)
脚本的参数列表在结构和行为上是否与可以在bash脚本中创建的任何对象(类似于数组,变量等)相同?
是的,不是。存在相似之处,主要是与数组相似。让我们尝试创建一个列表并将参数与数组arr
进行比较:
$#
与${#arr[@]}
$3
与${arr[3]}
${@:$n:1}
与${arr[$n]}
。但是数组切片也可以在数组上使用:${arr[@]:$n:1}
。set -- ${@:1:$((n-1))} newvalue ${@:$((n+1))}
与arr[$n]=newvalue
shift
,或者set -- "${@:2}"
vs arr=("${arr[@]:1}")
$0
$1
$2
,而您可以arr=(); arr[10]=value; arr[100]=value
。$(seq $#)
与${!arr[@]}
之比"$@"
与"${arr[@]}"
"$*"
与"${arr[*]}"
总结:
$@
和$<number>
访问脚本中的参数。$@
进行操作,但是您不能轻松地分配和/或删除元素。shift
命令,用于转移参数。$@
$*
$#
和$<number>
以及shift
和set
命令由POSIX shell指定。 Bash阵列仅在bash上可用。到您的脚本:
argvariable="$@"
展开$@
并使用IFS
加入。因此,您将以一个字符串结尾。这等于argvariable="$*"
。这样就避免了争论的逃逸。countargs="0"
for x in "${@}"
do
countargs=$(printf '%s\n' "1+$countargs" | bc)
printf '%s\n' "$countargs: '$x'"
done
可以简化为计算ex。 print %.0s
输出中的换行符:countargs=$(printf "%.0s\n" "$@" | wc -l)
。另外,您可以使用一个简单的帮助功能:cntarg() { echo "$#"; }; countargs=$(cntarg "$@")
。做$(printf '%s\n' "1+$countargs" | bc)
是一个过大的技巧-shell支持expr
命令,bash支持算术扩展$((...))
。您可以countargs=$((countargs+1))
甚至((countargs++))
来增加变量。"${argvariable[@]}"
-argvariable
不是数组。做"${argvariable[@]}"
等于"$argvariable"
。有没有一种方法可以将脚本的arglist复制到新对象,可以使用此一行printf命令对其进行检查?
将列表保存到数组中,就像在declare -a argarray=
命令中一样。
argarray=("$@")
然后您可以像在argarray
上一样在$@
上进行访问和操作。
答案 1 :(得分:0)
回答“是否有一种方法可以将脚本的arglist复制到可以使用此一行printf命令检查的新对象?”
之后
set -- 'The dog ate the "mouse" ' but the cat\?
代码
argarray=( "$@" )
printf 'arguments:%s\n' "${argarray[@]}"
产生的输出与
完全相同printf 'arguments:%s\n' "$@"
关于“脚本的参数列表在结构和行为上是否与可以在bash脚本中创建的任何对象(类似于数组,变量等)相同?”,最接近的“对象”参数列表(位置参数)是数组。数组的功能要强大得多。例如,可以单独添加,设置或删除数组元素。并且数组可以是稀疏的。参见Positional Parameters (Bash Reference Manual)和Arrays (Bash Reference Manual)。
请注意,可以使用以下命令打印计数的数组元素列表:
arg_idx=0
for arg in "${argarray[@]}" ; do
printf "%d: '%s'\\n" $((++arg_idx)) "$arg"
done
答案 2 :(得分:0)
答案
有没有一种方法可以将脚本的arglist复制到新对象,可以使用此一行printf命令对其进行检查?
明确表示“是。请使用数组,但请正确处理。”我的示例代码中最重要的缺点是以下
printf 'argarray:%s\n' "$argarray"
,下面已更正。因此,有必要在脚本开始时例行创建argarray
。然后将参数本身保留下来以供以后参考。
请注意,对于数组,检查元素本身不不可用的另一种方法是declare -p argarray
。
由于响应而得到纠正的小缺点
在此示例代码的底部,我保留了“字符串”处理,以提醒您将参数转换为字符串是一个坏主意。
#!/bin/bash
# Only for demonstration purposes, override all arguments.
set -- 'The dog ate the "mouse" ' but the cat?
# Create an array from script arguments.
declare -a argarray=( "$@" )
# Create a variable from script arguments.
argstring="$@"
# Various ways of trying to inspect script arguments.
printf 'arguments, printf:%s\n' "$@"
declare -p @
printf 'arguments indexed, loop:\n'
countargs="0"
for x in "${@}"
do
countargs=$((countargs+1));
printf '%s\n' "$countargs: '$x'"
done
printf '\n'
# Various ways of trying to inspect argarray.
printf 'argarray, printf:%s\n' "${argarray[@]}"
declare -p argarray
printf 'argarray indexed, loop:\n'
countargs="0"
for x in "${argarray[@]}"
do
countargs=$((countargs+1));
printf '%s\n' "$countargs: '$x'"
done
printf '\n'
# Various ways of trying to inspect argstring.
printf 'argstring, printf:%s\n' "$argstring"
declare -p argstring
printf 'argstring indexed, curly brackets, loop:\n'
countargs="0"
for x in "${argstring[@]}"
do
countargs=$((countargs+1));
printf '%s\n' "$countargs: '$x'"
done
printf 'argstring indexed, not bracketed, loop:\n'
countargs="0"
for x in $argstring
do
countargs=$((countargs+1));
printf '%s\n' "$countargs: '$x'"
done
printf '\n'
结果:
> bash-example.sh
arguments, printf:The dog ate the "mouse"
arguments, printf:but
arguments, printf:the
arguments, printf:cat?
/Users/BNW/u/kh/bin/bash-example.sh: line 11: declare: @: not found
arguments indexed, loop:
1: 'The dog ate the "mouse" '
2: 'but'
3: 'the'
4: 'cat?'
argarray, printf:The dog ate the "mouse"
argarray, printf:but
argarray, printf:the
argarray, printf:cat?
declare -a argarray='([0]="The dog ate the \"mouse\" " [1]="but" [2]="the" [3]="cat?")'
argarray indexed, loop:
1: 'The dog ate the "mouse" '
2: 'but'
3: 'the'
4: 'cat?'
argstring, printf:The dog ate the "mouse" but the cat?
declare -- argstring="The dog ate the \"mouse\" but the cat?"
argstring indexed, curly brackets, loop:
1: 'The dog ate the "mouse" but the cat?'
argstring indexed, not bracketed, loop:
1: 'The'
2: 'dog'
3: 'ate'
4: 'the'
5: '"mouse"'
6: 'but'
7: 'the'
8: 'cat?'