检查 Bash 中的数组中是否包含任何子字符串

Check if any substring is contained in an array in Bash

假设我有一个字符串,

a="This is a string"

和一个数组,

b=("This is my" "sstring")

如果 a 的任何子字符串位于 b 中,我想执行 if 条件,这是真的,因为“This is”是 [= 的第一个元素的子字符串16=].

如果有两个字符串,我知道如何检查 $x 是否是 $y 的子字符串,使用

if [[ $y == *$x* ]]; then
 #Something
fi

但由于 $x 是一个字符串数组,我不知道如何在不必显式循环遍历数组的情况下执行此操作。

您可以将 $a 拆分为一个数组,然后循环两个数组以查找匹配项:

a="this is a string"
b=( "this is my" "string")

# Make an array by splitting $a on spaces
IFS=' ' read -ra aarr <<< "$a"

for i in "${aarr[@]}"
do 
  for j in "${b[@]}"
  do
    if [[ $j == *"$i"* ]]; then
      echo "Match: $i : $j"
      break
    fi
  done
done

# Match: this : this is my
# Match: is : this is my
# Match: string : string

如果您需要处理 $a 中的子字符串(例如 this isis my 等),那么您将需要遍历数组,生成所有可能的子字符串:

for (( length=1; length <= "${#aarr[@]}"; ++length )); do
  for (( start=0; start + length <= "${#aarr[@]}"; ++start )); do
    substr="${aarr[@]:start:length}"
    for j in "${b[@]}"; do
      if [[ $j == *"${substr}"* ]]; then
        echo "Match: $substr : $j"
        break
      fi
    done
  done
done

# Match: this : this is my
# Match: is : this is my
# Match: string : string
# Match: this is : this is my

下面是如何将字符串 a 的最大单词数匹配到数组 b 的条目:

#!/usr/bin/env bash

a="this is a string"
b=("this is my" "string" )

# tokenize a words into an array
read -ra a_words <<<"$a"

match()
{
  # iterate entries of array b
  for e in "${b[@]}"; do

    # tokenize entry words into an array
    read -ra e_words <<<"$e"

    # initialize counter/length to the shortest MIN words count
    i=$(( ${#a_words[@]} < ${#e_words[@]} ? ${#a_words[@]} : ${#e_words[@]} ))

    # iterate matching decreasing number of words
    while [ 0 -lt "$i" ]; do

      # return true it matches
      [ "${e_words[*]::$i}" = "${a_words[*]::$i}" ] && return

      # decrease number of words to match
      i=$(( i - 1 ))
    done
  done

  # reaching here means no match found, return false
  return 1
}

if match; then
  printf %s\n 'It matches!'
fi

这可能就是您所需要的:

$ printf '%s\n' "${b[@]}" | grep -wFf <(tr ' ' $'\n' <<<"$a")
This is my

否则 - shell 是一种工具,用于操纵 files/processes 和对工具的调用排序。发明 shell 的人还为 shell 发明了 awk 来调用操作文本。您要做的是操作文本,因此您很有可能应该使用 awk 而不是 shell,因为无论您正在做什么,这项任务都是其中的一部分。

$ printf '%s\n' "${b[@]}" | 
awk -v a="$a" '
    BEGIN { split(a,words) }
    { for (i in words) if (index([=11=],words[i])) { print; f=1; exit} }
    END { exit !f }
'
This is my

上面假设 a 不包含任何反斜杠,如果可以的话,可以使用它来代替:

printf '%s\n' "${b[@]}" | a="$a" awk 'BEGIN{split(ENVIRON["a"],words)} ...'

如果 b 中的任何元素可以包含换行符,则:

printf '%s[=13=]' "${b[@]}" | a="$a" awk -v RS='[=13=]' 'BEGIN{split(ENVIRON["a"],words)} ...'