scp*_*ntm 44 arrays bash shell multidimensional-array
我正在计划一个脚本来管理我的Linux系统的某些部分,我正在决定是否要使用bash或python.
我更喜欢将此作为Bash脚本,因为命令更容易,但真正的决定因素是配置.我需要能够在配置文件中存储多维数组,以告诉脚本如何处理自身.使用bash在配置文件中存储简单的key = value对很容易,但我能想到做多维数组的唯一方法是使用两层解析引擎,类似于
array=&d1|v1;v2;v3&d2|v1;v2;v3
Run Code Online (Sandbox Code Playgroud)
但是marshall/unmarshall代码可能会成为一只熊,而且对于下一个必须管理这个问题的可怜的人来说,它远非用户友好.如果我不能轻易地在bash中执行此操作,我只需将配置写入xml文件并在python中编写脚本.
在bash中有一个简单的方法吗?
感谢大家.
Nah*_*eul 43
Bash不支持多维数组,也不支持哈希,似乎你想要一个值为数组的哈希.这个解决方案不是很漂亮,带有xml文件的解决方案应该更好:
array=('d1=(v1 v2 v3)' 'd2=(v1 v2 v3)')
for elt in "${array[@]}";do eval $elt;done
echo "d1 ${#d1[@]} ${d1[@]}"
echo "d2 ${#d2[@]} ${d2[@]}"
Run Code Online (Sandbox Code Playgroud)
Jah*_*hid 19
Bash没有多维数组.但您可以使用关联数组模拟一些类似的效果.以下是假装用作多维数组的关联数组的示例:
declare -A arr
arr[0,0]=0
arr[0,1]=1
arr[1,0]=2
arr[1,1]=3
echo "${arr[0,0]} ${arr[0,1]}" # will print 0 1
Run Code Online (Sandbox Code Playgroud)
如果未将数组声明为关联(with -A),则上述操作无效.例如,如果省略该declare -A arr行,echo则将打印2 3而不是0 1,因为0,0,1,0这将被视为算术表达式并计算为0(逗号运算符右侧的值).
Pau*_*ake 14
这对我有用.
# Define each array and then add it to the main one
SUB_0=("name0" "value0")
SUB_1=("name1" "value1")
MAIN_ARRAY=(
SUB_0[@]
SUB_1[@]
)
# Loop and print it. Using offset and length to extract values
COUNT=${#MAIN_ARRAY[@]}
for ((i=0; i<$COUNT; i++))
do
NAME=${!MAIN_ARRAY[i]:0:1}
VALUE=${!MAIN_ARRAY[i]:1:1}
echo "NAME ${NAME}"
echo "VALUE ${VALUE}"
done
Run Code Online (Sandbox Code Playgroud)
这是基于这个答案
独立于所使用的shell(sh,ksh,bash,...),以下方法对于n维数组非常有效(该示例涵盖了二维数组).
在样本中,行分隔符(第一维)是空格字符.为了引入字段分隔符(第二维),使用标准的unix工具tr.可以以相同的方式使用用于附加尺寸的附加分离器.
当然这种方法的表现不是很好,但如果性能不是一个标准,这种方法非常通用,可以解决许多问题:
array2d="1.1:1.2:1.3 2.1:2.2 3.1:3.2:3.3:3.4"
function process2ndDimension {
for dimension2 in $*
do
echo -n $dimension2 " "
done
echo
}
function process1stDimension {
for dimension1 in $array2d
do
process2ndDimension `echo $dimension1 | tr : " "`
done
}
process1stDimension
Run Code Online (Sandbox Code Playgroud)
该示例的输出如下所示:
1.1 1.2 1.3
2.1 2.2
3.1 3.2 3.3 3.4
Run Code Online (Sandbox Code Playgroud)
小智 7
如果您想使用 bash 脚本并使其易于阅读,建议将数据放入结构化 JSON 中,然后在您的 bash 命令中使用轻量级工具 jq来遍历数组。例如使用以下数据集:
[
{"specialId":"123",
"specialName":"First"},
{"specialId":"456",
"specialName":"Second"},
{"specialId":"789",
"specialName":"Third"}
]
Run Code Online (Sandbox Code Playgroud)
您可以使用 bash 脚本和 jq 遍历这些数据,如下所示:
function loopOverArray(){
jq -c '.[]' testing.json | while read i; do
# Do stuff here
echo "$i"
done
}
loopOverArray
Run Code Online (Sandbox Code Playgroud)
输出:
{"specialId":"123","specialName":"First"}
{"specialId":"456","specialName":"Second"}
{"specialId":"789","specialName":"Third"}
Run Code Online (Sandbox Code Playgroud)
经过大量的反复试验,我实际上发现 bash 上最好、最清晰和最简单的多维数组是使用常规 var。是的。
优点:你不必遍历一个大数组,你可以只回显 "$var" 并使用 grep/awk/sed。它简单明了,您可以拥有任意数量的列。
例子:
$ var=$(echo -e 'kris hansen oslo\nthomas jonson peru\nbibi abu johnsonville\njohnny lipp peru')
$ echo "$var"
kris hansen oslo
thomas johnson peru
bibi abu johnsonville
johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
$ echo "$var" | grep peru
thomas johnson peru
johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
$ echo "$var" | sed -n -E '/(.+) (.+) peru/p'
thomas johnson peru
johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
$ echo "$var" | awk '{print $2}'
hansen
johnson
abu
johnny
Run Code Online (Sandbox Code Playgroud)
$ echo "$var" |grep peru|grep thomas|awk '{print $2}'
johnson
Run Code Online (Sandbox Code Playgroud)
您能想到的任何查询......超级简单。
$ var=$(echo "$var"|sed "s/thomas/pete/")
Run Code Online (Sandbox Code Playgroud)
$ var=$(echo "$var"|sed "/thomas/d")
Run Code Online (Sandbox Code Playgroud)
$ var=$(echo "$var"|sed -E "s/(thomas) (.+) (.+)/\1 test \3/")
$ echo "$var"
kris hansen oslo
thomas test peru
bibi abu johnsonville
johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
$ for i in "$var"; do echo "$i"; done
kris hansen oslo
thomas jonson peru
bibi abu johnsonville
johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
我发现的唯一问题是您必须始终引用 var(在示例中;var 和 i),否则事情将如下所示
$ for i in "$var"; do echo $i; done
kris hansen oslo thomas jonson peru bibi abu johnsonville johnny lipp peru
Run Code Online (Sandbox Code Playgroud)
如果您的输入中有空格,那么无疑有人会说它不起作用,但是可以通过在输入中使用另一个分隔符来解决这个问题,例如(现在使用 utf8 字符来强调您可以选择您的输入不会包含,但您可以选择任何 ofc):
$ var=$(echo -e 'field one?field two hello?field three yes moin\nfield 1?field 2?field 3 dsdds aq')
$ for i in "$var"; do echo "$i"; done
field one?field two hello?field three yes moin
field 1?field 2?field 3 dsdds aq
$ echo "$var" | awk -F '?' '{print $3}'
field three yes moin
field 3 dsdds aq
$ var=$(echo "$var"|sed -E "s/(field one)?(.+)?(.+)/\1?test?\3/")
$ echo "$var"
field one?test?field three yes moin
field 1?field 2?field 3 dsdds aq
Run Code Online (Sandbox Code Playgroud)
如果您想在输入中存储换行符,您可以在输入之前将换行符转换为其他内容,并在输出时再次将其转换回(或不使用 bash...)。享受!