只需分配所有变量并同时写入输出即可。
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
现在,如果您这样做:
f ; echo "$a $b $c"
您的输出是:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
请注意,这是完全POSIX可移植的代码。我最初将其设置c=
为''
null字符串是因为参数扩展将并发变量赋值+求值限制为仅数字(如$((var=num))
)或空值或不存在的值-换句话说,您无法同时将变量设置和求值为任意字符串如果该变量已经分配了值。因此,在尝试之前,请确保它为空。如果c
在尝试分配它之前没有清空,则扩展将仅返回旧值。
只是为了演示:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval
是不是分配给$c
内联,因为oldval
扩展为${word}
,而内嵌$((
算术=
分配))
总是发生。但是如果$c
没有 oldval
并且为空或未设置...
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
c= a=$((a+a))
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval 8
...然后newval
立即分配给并扩展为$c
。
所有其他方式都需要某种形式的二次评估。例如,假设我希望将输出分配f()
给一个name
在另一点命名的变量var
。如当前所写,如果没有在调用者的作用域中设置var,这将无法工作。但是,另一种方式可能看起来像这样:
f(){ fout_name= fout= set -- "${1##[0-9]*}" "${1%%*[![:alnum:]]*}"
(: ${2:?invalid or unspecified param - name set to fout}) || set --
export "${fout_name:=${1:-fout}}=${fout:=$(date): $((a=${a:-50}+1)) $((b=${b:-100}-4))}"
printf %s\\n "$fout"
}
f &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$a" "$b"
我在下面提供了一个格式更好的示例,但是,如上所示,输出为:
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
51
96
或使用其他$ENV
或参数:
b=9 f myvar &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$myvar" \
"$a" "$b"
###OUTPUT###
Tue Jul 1 19:56:42 PDT 2014: 52 5
myvar
Tue Jul 1 19:56:42 PDT 2014: 52 5
Tue Jul 1 19:56:42 PDT 2014: 52 5
52
5
进行两次评估时,最棘手的事情可能是确保变量不会中断引号并执行随机代码。评估变量的次数越多,获得的难度就越大。参数扩展在这里有很大帮助,export
相对而言,使用起来eval
更安全。
在上述例子中f()
第一分配$fout
的''
空字符串,然后设置位置PARAMS到测试为有效的变量名。如果两个测试均未通过,则会向发出一条消息,stderr
并将的默认值fout
分配给$fout_name
。但是,无论进行何种测试,$fout_name
始终将其分配给fout
您指定的名称,或者始终将其分配给您指定的名称,$fout
以及(可选)始终将指定的名称分配给函数的输出值。为了证明这一点,我编写了这个for
小循环:
for v in var '' "wr;\' ong"
do sleep 10 &&
a=${a:+$((a*2))} f "$v" || break
echo "${v:-'' #null}"
printf '#\t"$%s" = '"'%s'\n" \
a "$a" b "$b" \
fout_name "$fout_name" \
fout "$fout" \
'(eval '\''echo "$'\''"$fout_name"\")' \
"$(eval 'echo "$'"$fout_name"\")"
done
它与一些变量名和参数扩展一起使用。如果您有任何疑问,请问。这只是运行在已经在这里所代表的功能相同的几行。至少值得一提的是,$a
和$b
变量的行为不同,这取决于它们是在调用时定义还是已设置。尽管如此,for
除了格式化数据集和由所提供的数据外,几乎什么都不做f()
。看一看:
###OUTPUT###
Wed Jul 2 02:50:17 PDT 2014: 51 96
var
# "$a" = '51'
# "$b" = '96'
# "$fout_name" = 'var'
# "$fout" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:27 PDT 2014: 103 92
'' #null
# "$a" = '103'
# "$b" = '92'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:37 PDT 2014: 207 88
wr;\' ong
# "$a" = '207'
# "$b" = '88'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
$a
和$b
在本地变量f
功能。您可以使用export
它们,但这似乎很粗略。