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

Bash“if number in array”还考虑部分匹配。如何解决这个问题?,bash,Bash,我编写了以下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 但是,对于步骤0、25和75,它输入if语

我编写了以下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
但是,对于步骤0、25和75,它输入if语句并执行某些操作,而我希望它输入else语句并执行其他操作。如何使我的正则表达式更具体或重写if语句


谢谢

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

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

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

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

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

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
  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

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

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

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

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

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

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

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

NStep=25
NTotal=435
Redone=('375' '400' '425' 'last')
for i in $(seq 0 $NStep $NTotal)
do
    if printf "%s\0" "${Redone[@]}" | grep -F -x -q -z "$i"; then
    # or if printf "%s\n" "${Redone[@]}" | grep -F -x -q "$i";
        echo "do something"
    else
        echo "do something else"
    fi
done
但我认为只使用您不感兴趣的过滤元件会更简单:

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

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

NStep=25
NTotal=435
Redone=('375' '400' '425' 'last')
for i in $(seq 0 $NStep $NTotal)
do
    if printf "%s\0" "${Redone[@]}" | grep -F -x -q -z "$i"; then
    # or if printf "%s\n" "${Redone[@]}" | grep -F -x -q "$i";
        echo "do something"
    else
        echo "do something else"
    fi
done
但我认为只使用您不感兴趣的过滤元件会更简单:

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

问题中没有任何东西表明单词可以被空格包围。@Barmar:这就是[@]索引数组在=~regex match中展开的方式。不过,我没有在ManBash中看到它的记录。此外,这不是一个通用的解决方案,因为数组可以包含“375 400”作为单个元素。我误读了代码,认为它在数组元素上循环,而不是一次匹配整个数组。问题中没有任何东西表明单词可以被空格包围。@Barmar:这就是[@]索引数组在=~regex match中展开。不过,我没有在ManBash中看到它的记录。另外,这不是一个通用的解决方案,因为数组可以包含单个元素“375 400”。我误读了代码,认为它在数组元素上循环,而不是一次匹配整个数组。为什么要使用正则表达式?为什么不使用相等运算来查找精确匹配?因为这样我就必须添加一个额外的循环。这就是add-w to seqWhy regex?为什么不使用相等操作来查找精确匹配?因为这样我就必须添加一个额外的循环。答案是add-w to seq您的解决方案对我有效我使用的是GNU bash,版本4.2.462release。谢谢我正在使用GNU bash,版本4.2.462release,您的变通方法对我很有效。谢谢