Bash "if number in array" 也考虑部分匹配。如何解决这个问题?



我写了以下bash代码:

NStep=25
NTotal=435
Redone=('375' '400' '425' 'last')
for i in $(seq 0 $NStep $NTotal)
do
if [[ "${Redone[@]}" =~ "$i" ]]; then
echo "do something"
else
echo "do something else"
fi
done

但是,对于步骤02575,它进入if语句(并执行某些操作(,而我希望它输入 else 语句(并执行其他操作(。如何使我的正则表达式更具体或重写 if 语句?

谢谢

在 bash 中,正则表达式不必匹配整个字符串。你需要说数字应该用空格或字符串的开头或结尾括起来:

if [[ "${Redone[@]}" =~ (^| )"$i"( |$) ]]; then

使用关联数组,而不是索引数组。(另外,不要使用seq;请改用 C 样式的 for 循环。

NStep=25
NTotal=435
declare -A Redone=([375]= [400]= [425]= [last]=)
for ((i=0; i<= $NTotal; i+=$NStep))
do
if [[ -v Redone[$i] ]]; then
echo "do something"
else
echo "do something else"
fi
done

关联数组的键充当集合,-v(此处测试数组中是否存在给定键(充当成员资格运算符。


对于不允许将-v与索引数组名称(4.2 或更早版本(一起使用的bash版本,您可以回退到检查扩展是否未设置。

if [[ "${Redone[$i]+x}" = x ]]

由于您使用了 null 字符串作为每个字符串的值,因此仅当$i是数组中的键时,${Redone[$i]+x}才会扩展到x

正则表达式匹配会导致部分匹配,我更喜欢更具体的解决方案。

NStep=25
NTotal=435
Redone=('375' '400' '425' 'last')
for i in $(seq 0 $NStep $NTotal)
do
isPresent=0  
for redone in "${Redone[@]}"
do
if [ "${redone}" = "${i}" ]
then
isPresent=1
break
fi
done
if [[ "${isPresent}" -eq "1" ]]; then
echo "do something"
else
echo "do something else"
fi
done

有很多方法可以检查元素是否包含在数组中:

NStep=25
NTotal=435
Redone=('375' '400' '425' 'last')
for i in $(seq 0 $NStep $NTotal)
do
if printf "%s" "${Redone[@]}" | grep -F -x -q -z "$i"; then
# or if printf "%sn" "${Redone[@]}" | grep -F -x -q "$i";
echo "do something"
else
echo "do something else"
fi
done

但我认为只过滤您不感兴趣的元素会更简单:

comm -12 <(printf "%sn" "${Redone[@]}" | sort) <(seq 0 "$NStep" "$NTotal" | sort)
# outputs 375 400 425

或者,您可以使用join并对seq中的行进行编号,然后重新使用它们并进行一些替换:

# this will print 15 lines of 'do something else'
# and 3 lines with 'do something'
# exactly the same as the `for i in ...` loop above
join -22 -a2 -e "do something else" -o2.1,1.1 <(printf "%sn" "${Redone[@]}" | sort) <(seq 0 $NStep $NTotal | nl -w1 | sort -k2) |
sort -n -k1 |
cut -d' ' -f2- |
sed 's/[0-9]+/do something/'

最新更新