문자열 값이 배열 요소와 일치하는지 테스트

문자열 값이 배열 요소와 일치하는지 테스트

저는 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는 쉘 중에서 최악의 선택 중 하나입니다.

zsh특정 구분 기호로 문자열을 분할 하려면 전용 연산자인 split가 있습니다. 매개변수 확장 플래그:

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

( Bourne 쉘에서 @와 같이 빈 요소를 보존하기 위해 따옴표를 사용 )"$@"

배열에 주어진 요소가 있는지 확인하십시오.

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

분할하려면 ksh/sh에서와 같이 bash분할+glob 연산자(따옴표 없이 사용하는 것이 약간 어색함)를 사용할 수 있습니다 .$(...)

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 블록이 실행됩니다.

ukeys의 요소가 array 의 요소와 일치 aggr하는 경우 display=1.

관련 정보