Uno de los argumentos que recibe mi guión es una fecha en el siguiente formato: yyyymmdd
.
Quiero verificar si obtengo una fecha válida como entrada.
¿Cómo puedo hacer esto? Estoy tratando de usar una expresión regular como:[0-9]\{\8}
Uno de los argumentos que recibe mi guión es una fecha en el siguiente formato: yyyymmdd
.
Quiero verificar si obtengo una fecha válida como entrada.
¿Cómo puedo hacer esto? Estoy tratando de usar una expresión regular como:[0-9]\{\8}
Respuestas:
Puede usar la construcción de prueba [[ ]]
, junto con el operador de coincidencia de expresiones regulares =~
, para verificar si una cadena coincide con un patrón de expresiones regulares .
Para su caso específico, puede escribir:
[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"
O más una prueba precisa:
[[ $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
Es decir, puede definir una expresión regular en Bash que coincida con el formato que desee. De esta manera puedes hacer:
[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"
donde los comandos posteriores &&
se ejecutan si la prueba es exitosa, y los comandos posteriores ||
se ejecutan si la prueba no tiene éxito.
Tenga en cuenta que esto se basa en la solución de Aleks-Daniel Jakimenko en la verificación del formato de fecha de entrada del usuario en bash .
En otras conchas puedes usar grep . Si su shell es compatible con POSIX, haga
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
En pescado , que no es compatible con POSIX, puede hacer
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
grep
comandos con -E
flag.
sh
, fish
u otros proyectiles menos equipados.
En bash versión 3 puedes usar el operador '= ~':
if [[ "$date" =~ ^[0-9]{8}$ ]]; then
echo "Valid date"
else
echo "Invalid date"
fi
Referencia: http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF
NOTA: La cita en el operador coincidente dentro de los corchetes dobles, [[]], ya no es necesaria a partir de la versión 3.2 de Bash
Una buena manera de probar si una cadena es una fecha correcta es usar el comando 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
del comentario: se puede usar el formato
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
date -d 2017-11-14e
, devuelve el martes 14 de noviembre a las 05:00:00 UTC de 2017, pero eso rompería mi script.
Yo usaría en expr match
lugar de =~
:
expr match "$date" "[0-9]\{8\}" >/dev/null && echo yes
Esto es mejor que la respuesta actualmente aceptada de usar =~
porque =~
también coincidirá con cadenas vacías, lo que en mi humilde opinión no debería. Supongamos badvar
que no está definido, luego [[ "1234" =~ "$badvar" ]]; echo $?
da (incorrectamente) 0
, mientras expr match "1234" "$badvar" >/dev/null ; echo $?
da el resultado correcto 1
.
Tenemos que usar >/dev/null
para ocultar expr match
el valor de salida , que es el número de caracteres coincidentes o 0 si no se encuentra ninguna coincidencia. Tenga en cuenta que su valor de salida es diferente de su estado de salida . El estado de salida es 0 si se encuentra una coincidencia, o 1 en caso contrario.
En general, la sintaxis para expr
es:
expr match "$string" "$lead"
O:
expr "$string" : "$lead"
donde $lead
es una expresión regular Su exit status
será cierto (0) si lead
coincide con el líder rebanada de string
(¿Hay un nombre para esto?). Por ejemplo , expr match "abcdefghi" "abc"
salidas true
, pero expr match "abcdefghi" "bcd"
salidas false
. (Gracias a @Carlo Wood por señalar esto.
=~
no coincide con cadenas vacías, está haciendo coincidir una cadena con un patrón vacío en el ejemplo que da La sintaxis es string =~ pattern
, y un patrón vacío coincide con todo.
expr match "abcdefghi" "^" && echo Matched || echo No match
, y expr match "abcdefghi" "bcd" && echo Matched || echo No match
- ambos regresan "0\nNo match"
. Donde como coincidencia "a.*f"
volverá "6\nMatched"
. Por lo tanto, el uso de '^' en su ejemplo también es innecesario y ya está implícito.
=~
combinar cadenas vacías. Es que este comportamiento puede ser inesperado y puede causar errores. Escribí esta respuesta específicamente porque me quemé.
expr
está de acuerdo conmigo.
Cuando el uso de una expresión regular puede ser útil para determinar si la secuencia de caracteres de una fecha es correcta, no se puede usar fácilmente para determinar si la fecha es válida. Los siguientes ejemplos pasarán la expresión regular, pero son todas las fechas inválidas: 20180231, 20190229, 20190431
Entonces, si desea validar si su cadena de fecha (llamémosla datestr
) está en el formato correcto, es mejor analizarla date
y solicitar date
convertir la cadena al formato correcto. Si ambas cadenas son idénticas, tiene un formato válido y una fecha válida.
if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi