在条件中使用通配符来匹配字符串的开头

在条件中使用通配符来匹配字符串的开头

尝试让一个变量满足长度不定的文本字符串。字符串中重要的部分是前几个字符。

var1=hello  
if [ $var1 == hello ]; then  
    echo success  
fi

或者

var1=hello  
if [ $var1 == h*o ]; then  
    echo success  
fi

输出:成功

但由于我关心的是前 3 个字符左右,这听起来合乎逻辑,但却不起作用:

var1=hello  
if [ $var1 == hel* ]; then  
    echo success  
fi

输出:-bash:[:参数太多

由于我只关心前几个字符,因此我可以这样做:

var1=hello 
if [ ${var1:0:3} == hel ]; then 
    echo success  
fi

那样可行,但我正在寻找出现该错误的原因的解释以及可能的更好的书面解决方案。

答案1

当您使用类似这样的*in时if,它将进行文件名扩展。因此,在第一个实例中,h*o可能与当前目录中的文件匹配,因此测试通过。

匹配hel*到多个文件,因此命令的参数太多if

尝试使用if [[ $var1 == hel* ]]; then

双括号将测试变成正则表达式,并且*通配符将按预期工作。

答案2

我有一个技巧,用于在不使用内置 bash 正则表达式的情况下破解正则表达式。示例为 #2。其工作原理是,如果 grep 不匹配任何内容,则不返回任何输出(因此不存在字符串)。因此有两个测试,-z 表示“空字符串”,-n 表示“有数据”。

if [ -n "`echo $var1 | grep -e 'h.*o'`" ] ; then
  echo 'water found'
fi

答案3

使用双括号在右表达式中启用模式匹配

if [[ "$var1" == hel* ]]

或使用正则表达式比较运算符。

if [[ "$var1" =~ ^hel.* ]]

(模式匹配和正则表达式不一样)

答案4

[[是 bash 特有的,使用起来grep很慢,因为它需要先启动一个新进程。有一种更简单、更快速的解决方案,适用于每个 POSIX 兼容 shell:

var1=hello  
case $var1 in
    hel*) echo success
esac

更通用的语法是:

case $var in
    <pattern1>) action1 ; action2 ; action3 ; ... ; actionN ;;
    <pattern2>) action1 ; action2 ; action3 ; ... ; actionN ;;
    <pattern3>) action1 ; action2 ; action3 ; ... ; actionN ;;
    *) action1 ; action2 ; action2 ; ... ; actionN ;;
esac

第一个匹配的模式定义要执行的操作。如果您想要else仅在没有模式匹配时运行的操作,请使用*模式,因为该模式将始终匹配。您可以使用 终止一组操作;;,如果下一条指令是,esac则这些操作是可选的。您还可以使用换行符来分隔指令,因此以下语法也是有效的:

case $var in
    <pattern>) 
       action1
       action2
       action3
       :
       actionN
    ;;

    *)
       action2
       action3
       :
       actionN
esac

在模式中,您可以使用*and ?,以及|表示“或”和[...],如[abcd](匹配这 4 个字母中的任一个) 或如[A-Z](匹配 A 到 Z 的所有字母,以及!否定匹配。例如

for var in abc 123 3a b5 934 "" 
do
    case $var in
        "" | *[!0-9]*) echo "\"$var\" is NOT an integer!" ;;
        *) echo "\"$var\" is an integer."
    esac
done

输出:

"abc" is NOT an integer!
"123" is an integer.
"3a" is NOT an integer!
"b5" is NOT an integer!
"934" is an integer.
"" is NOT an integer!

相关内容