#!/bin/bash
tank=(one two three)
x=two
unset tank[${x}]
echo ${tank[*]}
我想从数组中删除x,但不知何故它删除了数组的第一个元素。我该如何解决这个问题?
答案 0 :(得分:4)
您有一个索引数组,因此[...]
中的值被视为算术表达式以生成整数索引。假设这种表达式中的字符串是参数名称,未定义的参数评估为零。由于two
未定义,因此您的尝试将被评估为
unset tank[${x}] -> unset tank[two] -> unset tank[0]
要安全地从数组中删除项目,您需要遍历数组,将不匹配的项目复制到新数组,然后将新数组分配回旧名称。这可以防止拆分可能包含空格的数组元素。
x=two
new_tank=()
for i in "${tank[@]}"; do
if [[ $i != $x ]]; then
new_tank+=("$i")
fi
done
tank=( "${new_tank[@]}" )
更简洁,正如gniourf_gniourf指出的那样:
for i in "${!tank[@]}"; do
[[ ${tank[i]} = $x ]] && unset tank[i]
done
根据您的应用程序的不同,您可能需要考虑使用关联数组。
declare -A tank
tank=([one]=1 [two]=2 [three]=3) # Using the keys as the actually elements
x=two
unset tank[$x]
# Prove that two is really gone, with no hole left behind.
for i in "${!tank[@]}"; do
echo "$i"
done
答案 1 :(得分:1)
由于无法与正则表达式^two$
完全匹配元素,因此我看到的唯一方法是重建新数组,使用test
或{{1}排除不需要的元素执行完全匹配:
[[
答案 2 :(得分:0)
编辑user2997549当心:altought解决方案似乎在这种情况下工作,一般都是错误的。以下命令为数组中的所有元素执行模式替换,这实际上仅在您的示例中有效,因为您完全控制了数组的内容。 PLease接受更常见的chepner答案并解决其他问题,所以我可以删除我的答案。
要按值(而非索引)完全删除元素,您需要一个新的数组,如:
newtank=( ${tank[@]/two/} )
如果你只是取消设置一个索引,那么这个洞仍然会在数组中;或者如果你能摆脱旧阵列
tank=( ${tank[@]/${x}/} )