web-dev-qa-db-fra.com

Expressions régulières dans une instruction de cas Bash

J'utilise le script suivant, qui utilise l'instruction case pour trouver le serveur.

    #!/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

Mais ça ne fonctionne pas. Regex travaille avec egrep mais pas avec case. échantillon O/P

./test-back.sh ws-23.Host.com
ws-23.Host.com
Unknown server

Une idée ?

36
Unni

La casse basique n'utilise pas d'expressions régulières, mais Correspondance de modèle de shell uniquement.

Par conséquent, au lieu de regex ws-[0-9]+\.Host\.com, Vous devez utiliser le modèle ws*.Host.com (Ou ws-+([0-9]).Host.com, mais cela semble un peu avancé et je n'ai jamais essayé cela :-)

44
che

case ne peut utiliser que des globes. Si vous voulez faire une correspondance regex, vous devrez utiliser une série de if-then-else-Elif-fi instructions, avec [[.

10

Si vous voulez affirmer que * correspond vraiment aux chiffres de ws*.Host.com et voulez utiliser case au lieu de if, Elif, Elif... vous pouvez utiliser quelque chose comme ça:

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

Mais cela ne fonctionne pas pour plus de 999 serveurs.

Si je devais faire un script pour ce cas d'utilisation, j'écrirais probablement quelque chose comme ça (parce que j'aime les regexes et la syntaxe des casse;)):

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
9
syjust

Voici un exemple d'utilisation de la construction 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

Je trouve qu'il est plus fiable de stocker les expressions régulières dans leurs propres variables.

5
mlowry

Vous pouvez également utiliser expr pour effectuer la correspondance; il fournit une syntaxe d'expression régulière de type grep qui devrait être suffisamment robuste pour cette application.

#!/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
4
tkocmathla

Je sais que c'est une question assez ancienne et ma solution n'est pas très différente de ce que @ syjust a déjà fourni, mais je voulais montrer que vous pouvez faire à peu près n'importe quoi au stade de la correspondance dans un case/esac déclaration.

$ 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

1
AnthonyK