有很多类似的问题,但我不明白任何答案作为以下问题的解决方案:
我想创建一个包含两个参数的 bash 函数,第一个是变量名,第二个是搜索字符串(用于文件搜索)。
因此,我希望变量名称保存找到的文件的数组。
我有一个包含以下文件的目录:
- .jpg
- b.tif
- c.jpg
该函数定义为:
search-files--fill-array()
{
local variable_name="${1}"
declare -a eval ${variable_name}
local search_string="${2}"
echo "${search_string}"
local nullglob_setting=$(shopt -p nullglob)
shopt -s nullglob
found_files=(${search_string})
eval "${nullglob_setting}"
eval ${variable_name}=(${found_files[@]})
}
但最后一行会导致语法错误。它应该将数组分配给作为函数第一个参数提供的变量,因此调用该函数:
search-files--fill-array my_variable_a "*.jpg"
所以想要的结果应该是
echo "${my_variable_a[@]}"
显示两个文件“a.jpg”和“c.jpg”作为数组,即
echo "${#my_variable_a[@]}"
结果应为“2”。
如果它不必是数组,解决方案是使用以下最后一行:
eval ${variable_name}=\${found_files}
没有任何成功,我还尝试使用 while 循环从旧数组形成新数组,但这也不起作用。
eval ${variable_name}="\${found_files[@]}"
生成my_variable_a
包含字符串但不包含数组的结果。
背景
也许我的做法是完全错误的。
为了明确起见:我想用一个数组填充一些变量,每个变量保存通过通配符找到的文件的文件名(对于不同的搜索“字符串”总是以相同的方式)。我只期望文件,而不考虑子目录,并且我必须确保结果始终可靠地排序。)
我想避免冗余代码。
该shopt
部分是必要的,以确保如果当前目录中不存在文件,则数组将填充零个条目,而如果没有 nullglob,则将有一个条目包含搜索“string”的内容。
解决方案
作为比利叔叔建议,我可以declare -n var
在这里使用。
工作功能:
search-files--fill-array()
{
declare -n function=$1
local shopt_setting=$BASHOPTS
shopt -s nullglob
function=($2)
[[ :$shopt_setting: = *:nullglob:* ]] || shopt -u nullglob
}
他提议的重置处理会nullglob
导致该函数不再包含任何函数eval
。你可以阅读例如这个堆栈交换帖子了解为什么避免eval
值得考虑。
答案1
使用变量引用:
search-files--fill-array()
{
typeset -n a=$1
local s=$BASHOPTS
shopt -s nullglob
a=($2)
[[ :$s: = *:nullglob:* ]] || shopt -u nullglob
}
prompt> touch foo.txt bar.txt
prompt> search-files--fill-array foo '*.txt'
prompt> typeset -p foo
declare -a foo=([0]="bar.txt" [1]="foo.txt")
help declare
了解更多详细信息(declare
是 的同义词typeset
)。
declare -a eval ${variable_name}
这将声明两个数组当地的对于该函数,一个命名为eval
,另一个命名为 的内容${variable_name}
。无论你给它们赋值什么,函数返回后它都会丢失。用于declare -g
使它们全球化。
eval ${variable_name}=(${found_files[@]})
=> 语法错误
echo foo=(bar)
与=> 语法错误相同。(
是一个元字符,它不能在任何地方使用,只能在命令的开头(例如, after ;
、&&
等)或作为分配给数组时使用的特殊语法的一部分。