我无法从bash中的关联数组中检索键列表 脚本。但是,当我尝试编写简化的MCVE时,一切都是如此 按预期工作,我不知道我在两者之间做了什么不同。
我正在编写一个bash脚本,需要从中读取一组首选项 一个文件并将它们存储在一个关联数组中。请注意,我正在使用XML和 我更喜欢使用Perl模块来读取文件,但脚本会 在大量系统上运行,其中大多数都没有正确的系统 安装了Perl模块,而且我几乎没有必要的模块 访问安装它们。无论如何,解析XML文件不是问题所在。
问题是,当我针对XML文件运行以下脚本时, 我正在从XML文件中读取的设置似乎正在保存到 关联数组。换句话说,以下代码按预期工作:
while read line
do
# Trimming code that sets key-val.
$config[$key]=$val
echo "${key}=${config[$key]}"
done
但是后来我在脚本中试图检索配置值时,什么都没有 似乎在那里。似乎配置数组已被清除 不知何故,但我不清楚在哪里或如何。
这是非工作脚本。
#! /bin/bash
# Configuration Array.
declare -A config
CONFIG_XML=./config.xml
# Extract key-value pairs.
echo "Extracting and setting initial key-value pairs:"
grep "^.*<setting.*id=.*$" $CONFIG_XML |
while read line
do
key=$(echo "${line}" | perl -pe "s|^.*id.*?=.*?[\'\"](.*?)[\'\"].*$|\1|")
val=$(echo "${line}" | perl -pe "s|^.*value.*?=.*?[\'\"](.*?)[\'\"].*$|\1|")
config[$key]="${val}"
# This line prints key=value pairs as expected.
echo "${key}=${config[$key]}"
done
# This loop does not print key=value pairs as expected.
echo -e "\n\nExtracting key-value pairs from associative array and printing:"
for key in "${!config[@]}"
do
echo "${key}=${config[$key]}"
done
echo -e "\n\nAlso doesn't work:\nkey1=${config[key1]}"
这是与脚本一起提供的config.xml文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<setting id="key1" value="val1" />
<setting id="key2" value="val2" />
<setting id="key3" value="val3" />
<setting id="key4" value="val4" />
<setting id="key5" value="val5" />
</config>
以下是我预期的简化MCVE的内容 失败,但是按预期工作:
declare -A aa
for i in {0..10}
do
key="KEY${i}"
val="VAL${i}"
aa[$key]=$val
done
for key in "${!aa[@]}"
do
# Prints key-value pairs as expected.
echo "${key}=${aa[$key]}"
done
答案 0 :(得分:2)
while
循环必须在当前shell中执行才能使对数组的更改生效。一种解决方案是使用流程替换而不是管道。
while read line
do
key=$(echo "${line}" | perl -pe "s|^.*id.*?=.*?[\'\"](.*?)[\'\"].*$|\1|")
val=$(echo "${line}" | perl -pe "s|^.*value.*?=.*?[\'\"](.*?)[\'\"].*$|\1|")
config[$key]="${val}"
# This line prints key=value pairs as expected.
echo "${key}=${config[$key]}"
done < <(grep "^.*<setting.*id=.*$" $CONFIG_X)
如果您使用的是bash
4.2或更高版本,则可以使用lastpipe
选项。
shopt -s lastpipe
grep "^.*<setting.*id=.*$" $CONFIG_XML | while read line; do
...
done