如何测试一个项目是否在 bash 数组中?

elb*_*rna 16 bash array

一个简单脚本的帮助

#!/bin/bash

array1=(
prova1
prova2
slack64
)

a="slack64"
b="ab"

if [ $a = $b ]
then
      echo "$a = $b : a is equal to b"
else
      echo "$a = $b: a is not equal to b"
fi
Run Code Online (Sandbox Code Playgroud)

这个脚本根本不起作用,我想要一个脚本来检查列表中是否存在 slack64(我使用数组),然后简单地给我,是存在或否。我不知道如何将数组与单个变量进行比较。

mr.*_*tic 24

使用不同类型的数组:而不是整数索引数组,使用关联数组,因此键(索引)是您将要检查的。bash-4.0或稍后需要为此。

declare -A array1=( 
 [prova1]=1  [prova2]=1  [slack64]=1
)

a=slack64
[[ -n "${array1[$a]}" ]] && printf '%s is in array\n' "$a"
Run Code Online (Sandbox Code Playgroud)

在上面我们并不真正关心值,为此它们只需要非空。您可以通过交换键和值将索引数组“反转”为新的关联数组:

declare -a array1=( 
 prova1 prova2 slack64
)
declare -A map    # required: declare explicit associative array
for key in "${!array1[@]}"; do map[${array1[$key]}]="$key"; done  # see below

a=slack64
[[ -n "${map[$a]}" ]] && printf '%s is in array\n' "$a"
Run Code Online (Sandbox Code Playgroud)

如果您有经常搜索的大型数组,这可以带来回报,因为关联数组的实现将比数组遍历循环执行得更好。但是它并不适合所有用例,因为它无法处理重复项(尽管您可以将该值用作计数器,而不仅仅是上面的 1),并且它不能处理空索引。

打破上面的复杂线,解释“反转”:

for key in "${!a[@]}"     # expand the array indexes to a list of words
do 
  map[${a[$key]}]="$key"  # exchange the value ${a[$key]} with the index $key
done
Run Code Online (Sandbox Code Playgroud)


Gil*_*not 17

直接的方法是使用循环进行迭代:

var=ab
for item in "${array[@]}"; do
    [[ $var == "$item" ]] && echo "$var present in the array"
done
Run Code Online (Sandbox Code Playgroud)


小智 10

如何检查 Bash 数组是否包含值


误报匹配

array=(a1 b1 c1 d1 ee)

[[ ${array[*]} =~ 'a' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'a1' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'e' ]] && echo 'yes' || echo 'no'
# output:
yes

[[ ${array[*]} =~ 'ee' ]] && echo 'yes' || echo 'no'
# output:
yes
Run Code Online (Sandbox Code Playgroud)

完全符合

为了寻找精确匹配,您的正则表达式模式需要在值之前和之后添加额外的空格,例如(^|[[:space:]])"VALUE"($|[[:space:]])

# Exact match

array=(aa1 bc1 ac1 ed1 aee)

if [[ ${array[*]} =~ (^|[[:space:]])"a"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
No

if [[ ${array[*]} =~ (^|[[:space:]])"ac1"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
Yes

find="ac1"
if [[ ${array[*]} =~ (^|[[:space:]])"$find"($|[[:space:]]) ]]; then
    echo "Yes";
else
    echo "No";
fi
# output:
Yes
Run Code Online (Sandbox Code Playgroud)

有关更多用法示例,示例来源在这里


Sté*_*las 9

zsh

array1=(
  prova1
  prova2
  slack64
)

a=slack64

if (( $array1[(Ie)$a] )); then
  printf '%s\n' "$a in array1"
fi
Run Code Online (Sandbox Code Playgroud)

数组I下标标志用于返回匹配的最右边元素的索引$a(如果没有找到则返回0);with e,它是精确/字面匹配,而不是模式匹配。


bash

由于 bash 的数组成员不能包含 NUL 字节(与 zsh 相反),如果您有 GNUgrep或兼容版本,您始终可以这样做:

if (( ${#array1[@]} )) && printf '%s\0' "${array1[@]}" | grep -zqxFe "$a"; then
  printf '%s\n' "$a in array1"
fi
Run Code Online (Sandbox Code Playgroud)

也就是说,打印 NUL 分隔的元素,并要求grep快速q找到存储在这些ero 分隔记录中的x表达式F的固定字符串匹配项。e$az


小智 5

您也可以为此使用 grep:

array1=(prova1 prova2 slack64)
a=slack64
if (printf '%s\n' "${array1[@]}" | grep -xq $a); 然后
    回声“它在”
菲

  • 假设数组元素不包含换行符(以及空格和通配符,因为你忘记引用 `$a`,并且不要以 `-` 开头,因为你忘记了 `--`)。您可以使用 `%s\0` 而不是 `%s\n` 并使用 `grep --null`(假设 GNU grep 或兼容),因为 bash 变量无论如何都不能包含 NUL 字符。您还需要专门处理空数组的情况(因为 printf 命令将打印与具有一个空元素的数组相同的内容)。另请注意,您无需在此处启动子shell。 (2认同)