StackExchange 专业人士您好!
我正在开发一个适用于 macOS 的 zsh 项目。我使用排版创建了三个关联数组来保存值,以及第四个数组来引用各个数组。是否可以迭代 arrCollection 以从每个成员数组中检索键/值对?请注意,下面数组中的键与我的生产脚本不同 - 它们只是键索引,而不是您可能在关联数组中找到的更具描述性的键。
我想我可以像这样使用参数扩展:
for k in $(sort <<< "${(kvF)arrCollection}"); do
echo "$arrCollection["${(kvF)k}"]"
done
但我不太正确。有人可以帮忙吗?预期输出将是由换行符分隔的所有三个数组中的所有项目的列表。
下面是完整的脚本示例。用法:arrTest.sh showAll
#!/bin/zsh
key=$1
typeset -A arrOne arrTwo arrThree
typeset -A arrCollection
#Plan is to use an array of arrays so that a for loop can be used later to loop
#through each key/value pair looking for a value that matches some pattern in an if statement
#(if statement not included here). In the showAll case, how can I use parameter expansion to print all
#of the values in each array? The if statement will further constrict what is actually echoed based on its
#value.
arrOne[1]="First"
arrOne[2]="Second"
arrOne[3]="Third"
arrOne[4]="Fourth"
arrTwo[1]="Purple"
arrTwo[2]="Orange"
arrTwo[3]="Red"
arrTwo[4]="Green"
arrTwo[5]="Blue"
arrThree[1]="First"
arrThree[2]="Red"
arrThree[3]="Planet"
arrThree[4]="Sun"
arrThree[5]="Moon"
arrThree[6]="Star"
#Array of arrays
arrCollection[1]=arrOne
arrCollection[2]=arrTwo
arrCollection[3]=arrThree
#Expect a parameter
if [ -z "$key" ]
then
echo "Please enter a parameter"
else
case "$key" in
showAll)
for k in $(sort <<< "${(kvF)arrCollection}"); do
#This is the part I am having trouble with
echo "$arrCollection["${(kvF)k}"]"
done
exit 1
;;
*)
echo "Something goes here"
exit 1
;;
esac
fi
答案1
当您的键是从 1 开始的连续十进制数时,不确定为什么您使用关联数组而不是普通数组,但如果我正确理解您想要什么,您可以这样做:
for key in "${(nok@)arrCollection}"; do
print -r - "Assoc $key: $arrCollection[$key]"
printf ' "%s" => "%s"\n' "${(@kvP)arrCollection[$key]}"
done
您的样本中应该给出类似以下内容:
Assoc 1: arrOne
"3" => "Third"
"4" => "Fourth"
"1" => "First"
"2" => "Second"
Assoc 2: arrTwo
"3" => "Red"
"4" => "Green"
"5" => "Blue"
"1" => "Purple"
"2" => "Orange"
Assoc 3: arrThree
"3" => "Planet"
"4" => "Sun"
"5" => "Moon"
"6" => "Star"
"1" => "First"
"2" => "Red"
或者也可以按键对每个关联的成员进行数字排序:
for key in "${(nok@)arrCollection}"; do
print -r - "Assoc $key: $arrCollection[$key]"
for assoc_key in "${(@knoP)arrCollection[$key]}"; do
printf ' "%s" => "%s"\n' "$assoc_key" "${${(P)arrCollection[$key]}[$assoc_key]}"
done
done
这会给出:
Assoc 1: arrOne
"1" => "First"
"2" => "Second"
"3" => "Third"
"4" => "Fourth"
Assoc 2: arrTwo
"1" => "Purple"
"2" => "Orange"
"3" => "Red"
"4" => "Green"
"5" => "Blue"
Assoc 3: arrThree
"1" => "First"
"2" => "Red"
"3" => "Planet"
"4" => "Sun"
"5" => "Moon"
"6" => "Star"
o
上面的键使用(顺序)和n
(数字)排序参数扩展标志。与这些元素相比,元素使用区域设置排序规则进行比较,但由十进制数字序列组成的部分除外。十进制数字序列被解释为十进制整数并进行数值比较。
sort
这与GNU 实现对-V
/选项的作用类似--version-sort
。
例如,因此foo2-3
会出现在 beforefoo10-3
和 before foo2-10
,但不能用于除正十进制整数以外的数字(-2
也会出现在 before-10
和2.3
before 2.10
)。
sort
要使用其他任意标准进行排序,虽然 zsh 中存在以内置方式执行此操作的复杂方法,但如果您可以保证元素不包含 NL 或 NUL 字符并且不为空,则可能更容易采用。
以 GNU 为例sort
:
for key in ${(0)"$(print -rNC1 -- ${(k)arrCollection} | sort -zg)"}
以数字方式循环非空键,但这次支持各种数字表示形式(包括 0x20、1e-1、无穷大、-20、0x3.fp5...)。
上面使用 NUL 分隔记录将列表提供给列表sort
并分割其输出,因此假设键不包含 NUL 字符。要改用 NL/LF 字符,请删除-N
,-z
并更改(0)
为(f)
。
1 和 NUL 字符必须单独处理,因为标准比较 API 会阻塞它们。