我对bash脚本感到困惑。
我有以下代码:
function grep_search() {
magic_way_to_define_magic_variable_$1=`ls | tail -1`
echo $magic_variable_$1
}
我希望能够创建一个变量名,其中包含命令的第一个参数,并承载例如ls的最后一行的值。
为了说明我想要的:
$ ls | tail -1
stack-overflow.txt
$ grep_search() open_box
stack-overflow.txt
那么,我应该如何定义/声明$magic_way_to_define_magic_variable_$1,我应该如何在脚本中调用它?
我已经试过eval, ${…}, \$${...},但我还是很困惑。
使用关联数组,命令名作为键。
# Requires bash 4, though
declare -A magic_variable=()
function grep_search() {
magic_variable[$1]=$( ls | tail -1 )
echo ${magic_variable[$1]}
}
如果你不能使用关联数组(例如,你必须支持bash 3),你可以使用declare来创建动态变量名:
declare "magic_variable_$1=$(ls | tail -1)"
并使用间接参数展开来访问该值。
var="magic_variable_$1"
echo "${!var}"
参见BashFAQ:间接-计算间接/引用变量。
使用声明
没有必要像其他答案一样使用前缀,也没有数组。只使用声明、双引号和参数展开。
我经常使用下面的技巧来解析包含1到n个参数的参数列表,格式为key=value otherkey=othervalue etc=etc,例如:
# brace expansion just to exemplify
for variable in {one=foo,two=bar,ninja=tip}
do
declare "${variable%=*}=${variable#*=}"
done
echo $one $two $ninja
# foo bar tip
但是展开argv列表就像
for v in "$@"; do declare "${v%=*}=${v#*=}"; done
额外的建议
# parse argv's leading key=value parameters
for v in "$@"; do
case "$v" in ?*=?*) declare "${v%=*}=${v#*=}";; *) break;; esac
done
# consume argv's leading key=value parameters
while test $# -gt 0; do
case "$1" in ?*=?*) declare "${1%=*}=${1#*=}";; *) break;; esac
shift
done
我希望能够创建一个包含该命令的第一个参数的变量名
script.sh文件:
#!/usr/bin/env bash
function grep_search() {
eval $1=$(ls | tail -1)
}
测试:
$ source script.sh
$ grep_search open_box
$ echo $open_box
script.sh
根据帮助评估:
作为shell命令执行参数。
你也可以使用Bash ${!间接展开,正如前面提到的,但是它不支持检索数组下标。
欲进一步阅读或示例,请查看BashFAQ/006关于Indirection的内容。
我们不知道有任何技巧可以在POSIX或Bourne shell中复制该功能,而不需要eval,这可能很难安全地做到。所以,考虑这是一个自担风险的使用黑客。
但是,您应该根据以下注意事项重新考虑使用间接方法。
Normally, in bash scripting, you won't need indirect references at all. Generally, people look at this for a solution when they don't understand or know about Bash Arrays or haven't fully considered other Bash features such as functions.
Putting variable names or any other bash syntax inside parameters is frequently done incorrectly and in inappropriate situations to solve problems that have better solutions. It violates the separation between code and data, and as such puts you on a slippery slope toward bugs and security issues. Indirection can make your code less transparent and harder to follow.
我最近一直在寻找更好的方法。联想数组对我来说太夸张了。看看我发现了什么
suffix=bzz
declare prefix_$suffix=mystr
...然后……
varname=prefix_$suffix
echo ${!varname}
从文档中可以看出:
The ‘$’ character introduces parameter expansion, command substitution, or arithmetic expansion. ...
The basic form of parameter expansion is ${parameter}. The value of parameter is substituted. ...
If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of indirection. Bash uses the value formed by expanding the rest of parameter as the new parameter; this is then expanded and that value is used in the rest of the expansion, rather than the expansion of the original parameter. This is known as indirect expansion. The value is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion. ...