提问人:nooblag 提问时间:8/10/2023 更新时间:8/10/2023 访问量:117
Bash:根据文件名动态创建具有变量名称的变量
Bash: Dynamically create variables with the variable name based on a filename
问:
这个问题来自于减少 bash 脚本中一些重复的愿望,即检查文件中是否有内容,如果有,则将其第一行加载到同名变量中。
目前,对于贯穿始终的每个变量,都有几十行这样的行:
[[ -s './config/foo' ]] && read -r foo < './config/foo' || echo "problem with ./config/foo file"
[[ -s './config/bar' ]] && read -r foo < './config/bar' || echo "problem with ./config/foo file"
但是,与其经历太多这样的行,我想我也许可以通过使用数组来自动化这个过程(稍后,也可以用这种方法扩展到其他测试)。
因此,我从下面的代码开始,但想知道是否可以动态创建变量名称?我不知道该怎么做,也不知道这是否可能。我知道我可以通过去除路径来获取我们想要用于创建变量名称的文件的名称(例如,因此成为),但是如何将该结果转换为变量名称,然后将其设置为文件第一行的内容,就像原始脚本一样?${file##*/}
./config/foo
foo
这是我到目前为止所拥有的,我们可以从哪里得到这个名字:DYNAMIC_VARIABLE_NAME_HERE
${file##*/}
#!/bin/bash
# check and load config files
required_files=(
'./config/foo'
'./config/bar'
)
for file in "${required_files[@]}"; do
[[ -s "${file}" ]] && read -r DYNAMIC_VARIABLE_NAME_HERE < "${file}" || failed+=("${file}")
done
if [[ ${#failed[@]} -ne 0 ]]; then
echo "there is a problem with the following configuration files:"
for file in "${failed[@]}"; do
echo "${file}"
done
fi
# check
echo "foo: ${foo}"
echo "bar: ${bar}"
到目前为止的输出
foo:
bar:
所需输出
foo: [first line of ./config/foo file]
bar: [first line of ./config/bar file]
答:
4赞
markp-fuso
8/10/2023
#1
设置:
$ head foo bar
==> foo <==
1st line from foo
2nd line from foo
==> bar <==
1st line from bar
2nd line from bar
如果使用,您可以使用 nameref,例如:bash 4.2+
for fname in foo bar
do
declare -n curr_var="${fname}" # nameref
read -r curr_var < "${fname}"
done
这将生成:
$ typeset -p foo bar
declare -- foo="1st line from foo"
declare -- bar="1st line from bar"
这种方法的一个问题是......如何跟踪动态生成的变量名称。在这种情况下,我们已经在代码中对变量名称进行了硬编码,但是如果有 10 个文件,并且我们事先(以编程方式)不知道文件/变量名称是什么怎么办......您如何/在哪里跟踪变量名称?foo
bar
使用关联数组的不同方法:
unset myvar # insure array name not in use
declare -A myvar # define Associative array
for fname in * # for now assume this matches on files "foo" and "bar"
do
read -r myvar[$fname] < "${fname}"
done
这将生成:
$ typeset -p myvar
declare -A myvar=([bar]="1st line from bar" [foo]="1st line from foo" )
此外,我们可以通过仔细阅读数组的索引来获得变量名称的列表,例如:
for varname in "${!myvar[@]}" # loop through array indices
do
echo "varname = ${varname} : contents: ${myvar[$varname]}"
done
这将生成:
varname = bar : contents: 1st line from bar
varname = foo : contents: 1st line from foo
评论
2赞
nooblag
8/10/2023
伟大!我认为关联数组方法看起来更干净、更易于管理。感谢您的见解!
评论
array[$file]
mytFileToProcess=${file##*/}
for
$file