编写一个函数来检查字符串是否以某些内容开头或包含某些内容

No *_*ion 8 shell string function pattern-matching

我想编写一个函数来检查给定的变量,例如,var以给定字符串列表中的任何单词开头。这个列表不会改变。

为了实例化,让我们假设我想检查是否varaa,abc或开头3@3

此外,我想检查是否var包含字符>.

假设这个函数被调用check_func。我的预期用途看起来像

if check_func "$var"; then
    do stuff
fi
Run Code Online (Sandbox Code Playgroud)

例如,应该“做的东西”了 aardvarkabcdef3@3com.com12>5


我已经看到这个 SO 问题,其中用户提供了部分工作:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
Run Code Online (Sandbox Code Playgroud)

我的想法是我会遍历上面提到的列表并使用这个函数。我的困难在于不完全理解应该如何退出(或任何替代返回)来完成这项工作。

Kus*_*nda 11

check_prefixes () {
    value=$1

    for prefix in aa abc 3@3; do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}

check_contains_gt () {
    value=$1

    case $value in
        *">"*) return 0
    esac

    return 1
}

var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
    printf '"%s" contains ">" and starts with one of the prefixes\n' "$var"
fi
Run Code Online (Sandbox Code Playgroud)

我将测试分为两个功能。case ... esac一旦可以确定,两者都使用并返回成功(零)。如果没有匹配项,则返回失败 (1)。

为了使前缀列表更像一个动态列表,可以将第一个函数写为

check_prefixes () {
    value=$1
    shift

    for prefix do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}
Run Code Online (Sandbox Code Playgroud)

(要检查的值是第一个参数,我们将其保存在函数的参数列表中value,然后shift从参数列表中删除;然后我们遍历剩余的参数),然后将其调用为

check_prefixes "$var" aa abc 3@3
Run Code Online (Sandbox Code Playgroud)

第二个函数可以以类似的方式更改为

check_prefixes "$var" aa abc 3@3
Run Code Online (Sandbox Code Playgroud)

(检查某些任意子字符串),或

check_contains () {
    value=$1
    shift

    case $value in
        *"$1"*) return 0
    esac

    return 1
}
Run Code Online (Sandbox Code Playgroud)

(检查多个子字符串中的任何一个)


ImH*_*ere 6

对于 bash:

使用正则表达式的,你可以写的属性start^contain通过什么。

要检查的以或开头包含的正则表达式列表是:aa abc3@3 >

^aa ^abc ^3@3 >
Run Code Online (Sandbox Code Playgroud)

使其成为正确引用的列表并要求 bash 使用正则表达式 ( =~):

check_func() {
               matched=1
               for test_regex in '^aa' '^abc' '^3@3' '>'; do
                   if [[ $var =~ $test_regex ]] ; then
                       matched=0
                       break 
                   fi
               done
               return "$matched"
              }

var='aaIsAMatch'
if check_func; then
    echo "A match was found"
fi
Run Code Online (Sandbox Code Playgroud)

该函数对匹配列表和变量名称进行了硬编码。

给出数组变量中的正则表达式列表和要测试的第一个参数的值:

check_func() {
               local matched; matched=1
               for t in "${test_regex[@]}"; do
                   [[ $1 =~ $t ]] && { matched=0; break; } 
               done
               return "$matched"
              }


test_regex=('^aa' '^abc' '^3@3' '>')

if check_func 'aaIsAMatch'; then
    echo "A match was found"
fi
Run Code Online (Sandbox Code Playgroud)

该函数可以进一步改进以使用变量的名称(而不是值)作为第一个参数。

posix

由于 posix shell 中没有正则表达式,并且测试的唯一方法是 case 语句,因此我们必须使用 case 语句。遗憾的是,对于较旧的 shell([没有可用的扩展 globs][1]),我们必须循环进行所有测试。而且,球体需要是:

'aa*' 'abc*' '3@3*' '*>*'
Run Code Online (Sandbox Code Playgroud)

针对多个 glob 测试多个输入字符串的脚本示例:

check_func() { :
           matched=1
       value=$1; shift
           for t in "$@"; do
               case $value in $t) matched=0; #break;; esac
                  echo "matched $value with $t"
                  ;;
       esac
       done
           return "$matched"
         }


for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
        echo "========A match was found for \"$var\""
fi
done
Run Code Online (Sandbox Code Playgroud)

与您的请求完全匹配的函数的更简单版本:

check_func() { :
               matched=1
               value=$1; shift
                   for t in "$@"; do
                       case $value in $t) matched=0; break;; esac
                   done
               return "$matched"
             }
Run Code Online (Sandbox Code Playgroud)