我正在尝试遍历bash数组,如果它与正则表达式不匹配则取消设置值。代码块不会改变数组,任何想法?
for ((q=0; q<{#array[*]}; q++));
do
if [[ ${array[q]} =~ .*\.c$ ]]; then
:
else unset array[q]
done
答案 0 :(得分:1)
您错过了fi
语句的结束if
。但是,模式匹配在这里稍微简单一点,并且允许您使用!=
运算符来避免使用else
子句。
for ((q=0; q<${#array[*]}; q++));
do
if [[ ${array[q]} != *.c ]]; then
unset array[q]
fi
done
答案 1 :(得分:1)
您的问题是您继续在循环条件中评估${#array[*]}
,而不是先确定一次 , 。。
这样做,你最终会丢失循环中的数组元素。 [1]
请改为尝试:
#!/usr/bin/env bash
array=( foo.c non bar.c other ) # sample input
count=${#array[*]} # determine array size *beforehand*
for (( q=0; q < count; q++)); do
if [[ ${array[q]} =~ \.c$ ]]; then # note: no need for .* before \.c$
:
else
unset array[q]
fi
done
printf '%s\n' "${array[@]}" # prints 'foo.c' and 'bar.c'
dancancode's answer显示了一种更简洁的方法来预先分配数组元素:通过将其合并到循环条件的第一个语句 :
for (( q=0, count=${#array[@]}; q < count; ++q ))
但是,count
仍在 script 范围内隐式声明(就像q
),即不作用于for
循环
请注意,虽然取消设置单个数组元素正确地反映在元素计数{#array[*]}
中,但索引不更改,而最终会导致稀疏< / em> array。
因此,当您稍后枚举数组时,请使用:
,而不是循环遍历顺序索引for element in "${array[@]}"; ...
- 直接元素枚举for i in ${!array[@]}; do element=${array[i]}; ...
- 通过 list 进行枚举 - 可能是非顺序的索引(${!array[@]}
)。或者,您可以根据自身的副本重新定义稀疏数组将其转换为非稀疏数组(从0
开始的连续索引)。
array=( "${array[@]}" ) # convert to sequential indices starting at 0
[1] 问题的证明:
array=( one two three four )
for (( i=0; i < ${#array[@]}; i++)); do
echo "element: ${array[i]}; element count: ${#array[@]}"
unset array[i]
done
产量
element: one; element count: 4
element: two; element count: 3
换句话说:只处理了4个元素中的前2个,因为每次迭代中的数组计数(${#array[@]}
)减少(由于未设置的元素)导致提前终止循环。
注意暗示:${#array[@]}
始终反映元素 count ,无论数组是否稀疏(具有非顺序索引)。
答案 2 :(得分:0)
$array=('1' '2' '3' '4' 'abcd' '5')
$echo "${array[@]}"
1 2 3 4 abcd 5
$cnt=${#array[@]}
$for ((q=0;q<cnt;q++))
do
if [[ ${array[q]} =~ ^[0-9]$ ]]
then
:
else
unset array[q]
fi
done
$ echo "${array[@]}"
1 2 3 4 5
您可以使用的另一种简写就是这样
cnt=${#array[@]}
for ((q=0;q<cnt;q++))
do
[[ ${array[q]} =~ ^[0-9]$ ]] || unset array[q]
done
您在fi
中也遗漏了if
,语法错误
cnt=${#array[@]}
for ((q=0; q<cnt; q++));
do
if [[ ${array[q]} =~ .*\.c$ ]]; then
:
else
unset array[q]
fi
done
速记
cnt=${#array[@]}
for ((q=0; q<cnt; q++));
do
[[ ${array[q]} =~ .*\.c$ ]] || unset array[q]
done
答案 3 :(得分:0)
这是一个更大的脚本的一部分:
#!/bin/bash
shopt -s extglob nullglob
prune () { eval "for ((i=0, j=\${#$1[@]}; i<j; i++)); do [[ \${$1[i]} == $2 ]] && unset '$1[i]'; done; $1=(\"\${$1[@]}\")"; }
rpms=(*.rpm)
[[ $rpms ]] || exit 0
prune rpms '@(MQSeries|grafana|influxdb)*'
unset
实际上有效,但它在数组中留下了漏洞。如果重新定义数组以包含自身,则孔将消失。