web-dev-qa-db-fra.com

Vérifier si une chaîne correspond à une expression rationnelle dans le script Bash

L'un des arguments que mon script reçoit est une date au format suivant: yyyymmdd.

Je veux vérifier si j'obtiens une date valide.

Comment puis-je faire ceci? J'essaie d'utiliser un regex comme: [0-9]\{\8}

175
Peter Nijem

Tu peux dire:

[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"

Ou plus précis:

[[ $date =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes"
#           |^^^^^^^^ ^^^^^^ ^^^^^^  ^^^^^^ ^^^^^^^^^^ ^^^^^^ |
#           |   |     ^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^ |
#           |   |          |                   |              |
#           |   |           \                  |              |
#           | --year--   --month--           --day--          |
#           |          either 01...09      either 01..09     end of line
# start of line            or 10,11,12         or 10..29
#                                              or 30, 31

Autrement dit, vous pouvez définir une expression régulière dans bash correspondant au format souhaité. De cette façon, vous pouvez faire:

[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"

Notez que ceci est basé sur la solution d'Aleks-Daniel Jakimenko dans vérification du format de date entrée par l'utilisateur en bash .


Dans d'autres shells, vous pouvez utiliser grep . Si votre Shell est compatible POSIX, ne

(echo "$date" | grep -Eq  ^regex$) && echo "matched" || echo "did not match"

Dans poisson , ce qui n’est pas conforme à POSIX, vous pouvez le faire

echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
272
fedorqui

Dans la version 3 de bash, vous pouvez utiliser l'opérateur '= ~':

if [[ "$date" =~ "[0-9]\{8\}" ]]; then
    echo "Valid date"
else
    echo "Invalid date"
fi

Référence: http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF

NOTE: la citation dans l'opérateur de correspondance entre doubles crochets, [[]], n'est plus nécessaire à partir de Bash version 3.2

40
aliasav

Un bon moyen de vérifier si une chaîne correspond à une date correcte consiste à utiliser la commande date:

if date -d "${DATE}" >/dev/null 2>&1
then
  # do what you need to do with your date
else
  echo "${DATE} incorrect date" >&2
  exit 1
fi
28
Django Janny

Je voudrais utiliser expr match au lieu de =~:

expr match "$date" "[0-9]\{8\}" >/dev/null && echo yes

C'est mieux que la réponse actuellement acceptée d'utiliser =~ parce que =~ correspondra également à des chaînes vides, ce qui n'est pas le cas avec IMHO. Supposons que badvar ne soit pas défini, alors [[ "1234" =~ "$badvar" ]]; echo $? donne (incorrectement) 0, tandis que expr match "1234" "$badvar" >/dev/null ; echo $? donne le résultat correct 1.

Nous devons utiliser >/dev/null pour masquer expr match 'valeur de sortie, qui correspond au nombre de caractères correspondants ou à 0 si aucune correspondance n'est trouvée. Notez que sa valeur de sortie est différente de sa statut de sortie. Le statut de sortie est 0 si une correspondance est trouvée ou 1 sinon.

Généralement, la syntaxe pour expr est la suivante:

expr match "$string" "$lead"

Ou:

expr "$string" : "$lead"

$lead est une expression régulière. Son exit status sera vrai (0) si lead correspond à la tranche de tête de string (existe-t-il un nom pour cela?). Par exemple, expr match "abcdefghi" "abc"exit true, mais expr match "abcdefghi" "bcd" quitte false. (Nous remercions @Carlo Wood pour avoir signalé cela.

1
Penghe Geng

Lorsque l'utilisation d'une expression régulière peut être utile pour déterminer si la séquence de caractères d'une date est correcte, il est difficile de l'utiliser si vous voulez déterminer si la date est valide. Les exemples suivants passeront l'expression régulière, mais sont des dates non valides: 20180231, 20190229, 20190431

Donc si vous voulez valider si votre chaîne de date (appelons-la datestr) est dans le format correct, il est préférable de l'analyser avec date et de demander à date de convertir la chaîne en le bon format. Si les deux chaînes sont identiques, vous avez un format et une date valides.

if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
     echo "Valid date"
else
     echo "Invalid date"
fi
0
kvantour