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 en entrée.
Comment puis-je faire ceci? J'essaie d'utiliser une expression régulière comme:[0-9]\{\8}
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 en entrée.
Comment puis-je faire ceci? J'essaie d'utiliser une expression régulière comme:[0-9]\{\8}
Réponses:
Vous pouvez utiliser la construction de test, [[ ]]
avec l'opérateur de correspondance d'expressions régulières =~
, pour vérifier si une chaîne correspond à un modèle d' expression régulière .
Pour votre cas spécifique, vous pouvez écrire:
[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"
Ou un test 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"
où les commandes après &&
sont exécutées si le test réussit et les commandes après ||
sont exécutées si le test échoue.
Notez que cela est basé sur la solution d'Aleks-Daniel Jakimenko dans la vérification du format de date d'entrée utilisateur dans bash .
Dans d'autres shells, vous pouvez utiliser grep . Si votre shell est compatible POSIX, faites
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
Dans le poisson , qui n'est pas conforme à POSIX, vous pouvez faire
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
grep
commande avec -E
indicateur.
sh
, fish
ou d'autres obus moins équipés.
Dans la version bash 3, 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
REMARQUE: la citation dans l'opérateur de correspondance entre crochets, [[]], n'est plus nécessaire à partir de la version Bash 3.2
Un bon moyen de tester si une chaîne est une date correcte est d'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
du commentaire: on peut utiliser la mise en forme
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
date -d 2017-11-14e
il renvoie le 14 novembre 05:00:00 UTC 2017, mais cela casserait mon script.
J'utiliserais 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, =~
car =~
elle correspondra également à des chaînes vides, ce qui à mon humble avis ne devrait pas. Supposons que badvar
n'est pas défini, puis [[ "1234" =~ "$badvar" ]]; echo $?
donne (incorrectement) 0
, tandis que expr match "1234" "$badvar" >/dev/null ; echo $?
donne un résultat correct1
.
Nous devons utiliser >/dev/null
pour masquer expr match
la valeur de sortie de , qui est le nombre de caractères correspondants ou 0 si aucune correspondance n'a été trouvée. Notez que sa valeur de sortie est différente de son état de sortie . Le statut de sortie est 0 si une correspondance est trouvée, ou 1 sinon.
Généralement, la syntaxe de expr
est:
expr match "$string" "$lead"
Ou:
expr "$string" : "$lead"
où $lead
est une expression régulière. Ce exit status
sera vrai (0) si lead
correspond à la tranche principale de string
(Y a-t-il un nom pour cela?). Par exemple, expr match "abcdefghi" "abc"
quitte true
, mais expr match "abcdefghi" "bcd"
quitte false
. (Nous remercions @Carlo Wood de l'avoir signalé.
=~
ne correspond pas à des chaînes vides, vous comparez une chaîne à un modèle vide dans l'exemple que vous donnez. La syntaxe est string =~ pattern
, et un modèle vide correspond à tout.
expr match "abcdefghi" "^" && echo Matched || echo No match
- et expr match "abcdefghi" "bcd" && echo Matched || echo No match
- les deux reviennent "0\nNo match"
. Où que l'appariement "a.*f"
reviendra "6\nMatched"
. L'utilisation du '^' dans votre exemple est donc également inutile et déjà implicite.
=~
correspondance de chaînes vides. C'est que ce comportement peut être inattendu et provoquer des erreurs. J'ai écrit cette réponse précisément parce que j'ai été brûlé par elle.
expr
est d'accord avec moi.
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, elle ne peut pas être utilisée facilement pour déterminer si la date est valide. Les exemples suivants transmettront l'expression régulière, mais sont toutes des dates non valides: 20180231, 20190229, 20190431
Donc, si vous voulez valider si votre chaîne de date (appelons-la datestr
) est au format correct, il est préférable de l'analyser avec date
et de demander date
à convertir la chaîne au format correct. 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