我想定义并获取作为参数传递给函数的所有必需变量:
function explain_vars() {
echo "Explaining vars '$@':" >&2
for _var in "$@"; do
printf " $_var: '${!_var}'\n" >&2
done
printf "\n" >&2
}
function read_params() (
## Define local variables
_vars=(v1 v2 v3)
local ${_vars[@]}
## Read variables from input:
read ${_vars[@]} <<< "$@"
explain_vars "${_vars[@]}"
)
read take将所有参数放在指定的变量中,默认分隔符在这里是空格。因此,如果我将不同的字符串作为第二个参数传递,read
将仅存储第二个参数中的第一个字符串,并将所有其余字符串存储为以下参数:
$ read_params one "two dot one" "three" "four"
Explaining vars 'v1 v2 v3':
v1: 'one'
v2: 'two'
v3: 'dot one three four'
我们可以看到,变量v2不再与给定参数同步。此外,它无法读取空字符串:
$ read_params one "" " " '' ' ' "two dot one" "three" "four"
Explaining vars 'v1 v2 v3':
v1: 'one'
v2: 'two'
v3: 'dot one three four'
通过在函数内循环遍历所有参数变量$ @,可以区分变量:
function raw_params() (
echo "Explaining row parameters:"
for _v in "${@}"; do
printf " '$_v'\n"
done
)
$ raw_params one "" " " '' ' ' "two dot one" "three" "four"
Explaining row parameters:
'one'
''
' '
''
' '
'two dot one'
'three'
'four'
对我来说,read
命令提供了定义,控制和检查传递给函数的请求参数的好处和速度。但是,这仅适用于单个和非空的弦乐参数。是否可以读取变量中的所有不同参数,例如read
命令,但尊重空格和空参数?或者有更好的方法吗?
答案 0 :(得分:1)
我不确定您希望使用此代码完成什么,但这似乎可以解决三个输入参数的问题。也许它向你展示了前进的方向,即使它没有完全按照你的意愿行事。
read_params () (
## Define local variables
_vars=(v1 v2 v3)
local ${_vars[@]}
local i
for ((i=1; i<=$#; ++i)); do
## Read variables from input:
printf -v "${_vars[i-1]}" "${!i}"
done
explain_vars "${_vars[@]}"
)
答案 1 :(得分:1)
从原始问题看来read
命令未正确理解,read
是内置函数,读取一行标准输入,IFS
环境变量用作字段分隔符,-d
1}}选项允许更改记录分隔符(默认为换行符),有关详细信息,请参阅bash手册中的read
。
使用特殊变量"$@"
检索函数参数,bash语法分配数组只是
_vars=( "$@" ) # no space between variable name and = and no space between = and (
如果空格在变量名${!_var}
中无效,则扩展将无法编写错误bash: ...: bad substitution
,如果_var包含带空格的表达式。
function
, ()
关键字无用,在函数体周围使用括号而不是大括号{ ;}
会启动一个新的子shell。
答案 2 :(得分:0)
我根据tripleee
的回答在脚本中重写了我的函数。除了将空值(''和“”)分配给printf
之外,arrays
工作正常。为此,我们需要使用'%s'格式化传递给printf -v
的字符串。对于示例,我将一个参数数组传递给我的函数两次:每次将它们分配给我的常规本地参数;第二次将相同的参数传递给我的上一个本地数组变量。这是代码:
$ cat parse-local-vars.sh
#!/usr/bin/env bash
function explain_vars() {
echo "Explaining vars '$@':" >&2
for _var in "$@"; do
printf " $_var: '${!_var}'\n" >&2
done
}
function parse_params() (
#
# Stores given parameters in defined local variables _vars.
# Last variable will be treated as an array and
# remaining parameters will be stored therein.
#
## Define local variables
local _vars=(v1 v_empty_double_quote v_spaced_double_quote v_empty_single_quote v_spaced_single_quote v2_1 v3 v4 args)
local ${_vars[@]}
## Make sure we assign parameters to variables
[ ${#_vars[@]} -gt 0 ] \
|| return 1
_args_pos=$(( ${#_vars[@]}-1 ))
_args_counter=0
local p
for ((p=1; p<=$#; ++p)); do
## Read variables from input:
if [ $p -le $_args_pos ]; then
#printf -v "${_vars[p-1]}" '%s' "${!p}"
printf -v "${_vars[p-1]}" "${!p}"
else
#printf -v "${_vars[_args_pos]}[$_args_counter]" '%s' "${!p}"
printf -v "${_vars[_args_pos]}[$_args_counter]" "${!p}" # Without the '%s' assigning empty variable to an array does not work
_args_counter=$(( _args_counter+1 ))
fi
done
explain_vars "${_vars[@]}"
echo "exlaining array args[@]: '${args[@]}'"
for _v in "${args[@]}"; do
echo " >'$_v'"
done
)
params_to_test=(one "" " " '' ' ' "two dot one" "three" "four")
parse_params "${params_to_test[@]}" "${params_to_test[@]}"
正如我所看到的,这里我使用printf -v
而不格式化参数字符串(不使用'%s'
):
$ bash parse-local-vars.sh
Explaining vars 'v1 v_empty_double_quote v_spaced_double_quote v_empty_single_quote v_spaced_single_quote v2_1 v3 v4 args':
v1: 'one'
v_empty_double_quote: ''
v_spaced_double_quote: ' '
v_empty_single_quote: ''
v_spaced_single_quote: ' '
v2_1: 'two dot one'
v3: 'three'
v4: 'four'
args: 'one'
exlaining array args[@]: 'one two dot one three four' (6 values)
>'one'
>' '
>' '
>'two dot one'
>'three'
>'four'
空参数“”和“'不会传递给数组(6个值)。
通过切换以下注释来允许printf
的字符串格式:
printf -v "${_vars[_args_pos]}[$_args_counter]" '%s' "${!p}"
#printf -v "${_vars[_args_pos]}[$_args_counter]" "${!p}" # Without the '%s' as,signing empty variable to an array does not work
导致此输出:
$ bash parse-local-vars.sh
Explaining vars 'v1 v_empty_double_quote v_spaced_double_quote v_empty_single_quote v_spaced_single_quote v2_1 v3 v4 args':
v1: 'one'
v_empty_double_quote: ''
v_spaced_double_quote: ' '
v_empty_single_quote: ''
v_spaced_single_quote: ' '
v2_1: 'two dot one'
v3: 'three'
v4: 'four'
args: 'one'
exlaining array args[@]: 'one two dot one three four' (8 values)
>'one'
>''
>' '
>''
>' '
>'two dot one'
>'three'
>'four'
这是预期的结果,因为空字符串被正确分配给数组(8个值)。我还没弄清楚将空字符串传递给printf -v
的数组是怎么回事,但是使用带有printf -v
的格式化字符串似乎是安全的方法。欢迎任何更正,解释和改进。