测试字符串值是否与数组元素匹配

测试字符串值是否与数组元素匹配

我正在使用 bash 脚本并有一串逗号分隔的值string="string1,string2,string"。每个字符串中不会有任何嵌入的逗号或空格。想要测试字符串元素是否出现在数组中。

如何将字符串元素与任意数组的元素匹配?

string="element1,element2,element3"
array=($(echo $string | tr ',' ' '))
for i in "${array[@]}"; do
    if [ "$i" == "element2" ]; then
        echo "element found"
    fi
done

答案1

也许你可以这样做:

string=element1,element2,element3
element=element2
case ",$string," in
  (*,"$element",*) echo element is in string;;
  (*) echo it is not;;
esac

(标准sh语法)。

对于处理数组或分割字符串,bash 是 shell 中最糟糕的选择之一。

使用zsh, 要在给定分隔符上分割字符串,有一个专用运算符:split 参数扩展标志:

array=( "${(@s[,])string}" )

@以及用于保留空元素的引号,如"$@"Bourne shell 中的 )

检查数组是否有给定元素:

if (( $array[(Ie)$element] )); then
  print element is in the array
else
  print it is not
fi

要拆分bash,您可以使用 split+glob 运算符(使用不带引号的 有点尴尬$(...)),就像 ksh/sh 中一样:

IFS=, # split on , instead of the default of SPC/TAB/NL
set -o noglob # disable the glob part which you don't want
array=( $string'' ) # split+glob; '' added to preserve an empty trailing element
                    # though that means an empty $string is split into one empty
                    # element rather than no element at all

为了查找数组,bash 也没有专用的运算符,但您可以定义一个辅助函数:

is_in() {
  local _i _needle="$1"
  local -n _haystack="$2"
  for _i in "${_haystack[@]}"; do
    [ "$_i" = "$_needle" ] && return
  done
  false
}
if is_in "$element" array; then
  echo element is in the array
else
  it is not
fi

答案2

您可以设置有效单词列表的哈希表,然后(有效地)搜索第二个列表中的所有项目。

#! /bin/bash
#.. ./LookUp  04-Feb-2023: Paul_Pedant.

declare -A Hash     #.. Create at global scope.

Setup () {      #.. Set up a hash table of the required elements.

    local j; declare -a q
    #.. Make the input string into an array like: q=([0]="Monday" ...)
    IFS=, read -r -a q <<<"${1}"
    #.. Invert that array like: Hash([Monday]="0" ...)
    for j in "${!q[@]}"; do Hash+=(["${q[j]}"]="${j}"); done
}

Query () {      #.. Search for words in a list. 

    local s; declare -a q
    IFS=, read -r -a q <<<"${1}"
    for s in "${q[@]}"; do
        if [[ -z "${Hash[${s}]+x}" ]]; then
            printf '%s is missing\n' "${s}"
        else    
            printf '%s is index %s\n' "${s}" "${Hash[${s}]}"
        fi      
    done
}

    Setup "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday"

    Query "Tuesday,BadHairDay,Friday,Holiday,Sunday,Today,Monday,BadDay"

和测试:

$ ./LookUp 
Tuesday is index 1
BadHairDay is missing
Friday is index 4
Holiday is missing
Sunday is index 6
Today is missing
Monday is index 0
BadDay is missing
$ 

答案3

如果我正确理解你的问题,忽略将 csv 转换为数组的位,以下可以有时用于搜索数组中的元素,但是当涉及到潜在的空格/换行符以及可能更多时,有一些警告。

arr=(foo bar baz)
if [[ "${arr[*]}" =~ foo ]]; then
  echo "element found"
fi

答案4

我有以下解决方案

aggr=("bash" "resource" "rsync")
ukeys="resource,rsync"

if [[ "${aggr[@]}" =~ $(echo "$ukeys" | tr ',' '|') ]]; then
  echo "All strings exist in the array."
else
  echo "One or more strings do not exist in the array."
fi

这使用tr命令将字符串中的逗号替换为管道,创建可与=~运算符一起使用的正则表达式。该$( ... )语法用于运行 tr 命令并捕获其输出,然后将其用作=~运算符的模式。如果正则表达式与数组中的任何元素匹配,则将执行if块,表明字符串中的所有字符串都存在于数组中。

我想以这样的方式进行调整:如果 in 中的元素与ukeysarray 中的元素匹配aggr,则我设置display=1.

相关内容