Bash案例语句中的正则表达式

Unn*_*nni 39 regex bash glob case

我正在使用以下脚本,它使用case语句来查找服务器.

    #!/bin/bash
SERVER=$1;
echo $SERVER | egrep "ws-[0-9]+\.host\.com";
case $SERVER in
ws-[0-9]+\.host\.com) echo "Web Server"
;;
db-[0-9]+\.host\.com) echo "DB server"
;;
bk-[0-9]+\.host\.com) echo "Backup server"
;;
*)echo "Unknown server"
;;
esac
Run Code Online (Sandbox Code Playgroud)

但它没有用.正则表达式正在与egrep合作,但不与案例合作.样本O/P.

./test-back.sh ws-23.host.com
ws-23.host.com
Unknown server
Run Code Online (Sandbox Code Playgroud)

任何的想法 ?

che*_*che 47

Bash案例不使用正则表达式,而只使用shell模式匹配.

因此,ws-[0-9]+\.host\.com你应该使用模式代替正则表达式ws*.host.com(或者ws-+([0-9]).host.com,但看起来有点先进,我从来没有尝试过:-)


Ign*_*ams 10

case只能用globs.如果你想进行正则表达式匹配,那么你需要使用一系列if-then-else-elif-fi语句[[.

  • Ignacio意味着使用`[[`在级联的`if ... elif ... fi`语句中 (6认同)

小智 10

如果你想要断言,*真正匹配位数ws*.host.com,并希望使用case代替if,elif,elif...您可以使用类似的东西:

case $SERVER in
  ws-[0123456789][0123456789][0123456789].host.com) echo "Web Server" ;;
  db-[0123456789][0123456789][0123456789].host.com) echo "DB server" ;;
  bk-[0123456789][0123456789][0123456789].host.com) echo "Backup server" ;;
  *) echo "Unknown server" ;;
esac
Run Code Online (Sandbox Code Playgroud)

但这不适用于超过999台服务器.

如果我必须为这个用例创建一个脚本,我可能会写这样的东西(因为我喜欢正则表达式和case语法;)):

srv=`expr "$SERVER" : '^\(db\|bk\|ws\)-[0-9]\+\.host\.com$'`
echo -n "$SERVER : "
case $srv in
  ws) echo "Web Server" ;;
  db) echo "DB server" ;;
  bk) echo "Backup server" ;;
  *) echo "Unknown server !!!"
esac
Run Code Online (Sandbox Code Playgroud)

  • `case ... esac`的标准也可以写成`ws- [0-9] [0-9] [0-9] .host.com)`. (2认同)

mlo*_*wry 7

这是如何使用elif构造的示例。

#!/bin/bash
SERVER=$1;
regex_ws="^ws-[0-9]+\.host\.com$"
regex_db="^db-[0-9]+\.host\.com$"
regex_bk="^bk-[0-9]+\.host\.com$"
if [[ "${SERVER}" =~ $regex_ws ]]; then
  echo "Web Server"
elif [[ "${SERVER}" =~ $regex_db ]]; then
  echo "DB server"
elif [[ "${SERVER}" =~ $regex_bk ]]; then
  echo "Backup server"
else
  echo "Unknown server"
fi
Run Code Online (Sandbox Code Playgroud)

我发现将正则表达式存储在自己的变量中最可靠。


Ant*_*nyK 6

我知道这是一个相当古老的问题,我的解决方案与@syjust已经提供的解决方案没有太大区别,但我想表明您可以在case/esac语句的匹配阶段做任何事情。

$ cat case.sh && echo -e "#################\n" && bash case.sh ws-23.host.com
#!/bin/bash
SERVER=$1;
echo $SERVER | egrep "ws-[0-9]+\.host\.com";
case $SERVER in
  $(awk '{a=0}/ws-[0-9]*.host.com/{a=1}a' <<<${SERVER}))echo "Web Server";;
  $(awk '{a=0}/db-[0-9]*.host.com/{a=1}a' <<<${SERVER}))echo "DB Server";;
  $(awk '{a=0}/bk-[0-9]*.host.com/{a=1}a' <<<${SERVER}))echo "Backup Server";;
  *)echo "Unknown server";;
esac

#################

ws-23.host.com
Web Server

Run Code Online (Sandbox Code Playgroud)


din*_*ini 6

作为参考,但是在这个答案中已经提到了这一点,从man bash模式匹配部分提供了复合模式创建的规则:

可以使用以下一种或多种子模式形成复合模式:

?(pattern-list)
        匹配给定模式的零次或一次出现。
*(pattern-list)
        匹配给定模式的零次或多次出现。
+(pattern-list)
        匹配一个或多个给定模式。
@(pattern-list)
        匹配给定的模式之一。
!(pattern-list)
        匹配除给定模式之一之外的任何内容。

然而,使用这些扩展模式匹配需要extglob启用 shell 选项。

以下是当前问题的代码示例:

shopt -s extglob;
SERVER="ws-45454.host.com";
case $SERVER in
        ws-+([0-9])\.host\.com) echo "Web Server"
                ;;
        db-+([0-9])\.host\.com) echo "DB server"
                ;;
        bk-+([0-9])\.host\.com) echo "Backup server"
                ;;
        *)echo "Unknown server"
                ;;
esac;
shopt -u extglob;
Run Code Online (Sandbox Code Playgroud)

此外, this:shopt | grep extglob可用于检查其默认值。


tko*_*hla 5

您还可以使用expr它来进行匹配;它提供了类似 grep 的正则表达式语法,对于此应用程序来说应该足够强大。

#!/bin/bash

server=$1
if   expr "$server" : 'ws-[0-9]\+\.host\.com' >/dev/null; then echo "Web server"
elif expr "$server" : 'db-[0-9]\+\.host\.com' >/dev/null; then echo "DB server"
elif expr "$server" : 'bk-[0-9]\+\.host\.com' >/dev/null; then echo "Backup server"
else echo "Unknown server"
fi
Run Code Online (Sandbox Code Playgroud)