我需要创建一个Shell脚本,在其中一个参数将是格式为dd/mm/yyyy的日期。我的问题是,如何检查传递的日期参数是否真的遵循这个日期格式?我尝试使用以下grep命令:
if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$'
但它没有给出正确的格式,因为日期例如可以是33、34、(...),这并不是真正的正确格式。有人知道能够真正检查传递的日期是否遵循dd/mm/yyyy格式的方法吗?
我需要创建一个Shell脚本,在其中一个参数将是格式为dd/mm/yyyy的日期。我的问题是,如何检查传递的日期参数是否真的遵循这个日期格式?我尝试使用以下grep命令:
if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$'
但它没有给出正确的格式,因为日期例如可以是33、34、(...),这并不是真正的正确格式。有人知道能够真正检查传递的日期是否遵循dd/mm/yyyy格式的方法吗?
使用date
date "+%d/%m/%Y" -d "09/99/2013" > /dev/null 2>&1
is_valid=$?
日期字符串必须以“MM/DD/YYYY”格式表示。
如果不为0,则日期格式无效。
最简单的解决方案,仍然完美运作,如下:
if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1
...
它的含义是将两个检查组合在一起:
$1
是否符合此格式:NNNN-NN-NN
你需要这两个检查,因为:
date
也会退出并返回02016-13-45
这样的日期这个函数需要两个字符串输入:一个格式字符串和一个日期字符串。
格式字符串使用date命令中的代码,但不包括“+”符号。
如果提供的日期与给定的格式匹配,则该函数返回0,否则返回1。
代码(my_script.sh)
#!/bin/bash
datecheck() {
local format="$1" d="$2"
[[ "$(date "+$format" -d "$d" 2>/dev/null)" == "$d" ]]
}
date_test="$1"
echo $date_test
if datecheck "%d %b %Y" "$date_test"; then
echo OK
else
echo KO
fi
输出
$ ./my_script.sh "05 Apr 2020"
05 Apr 2020
OK
$ ./my_script.sh "foo bar"
foo bar
KO
首先,使用正则表达式检查输入的格式。然后使用awk切换到mm/dd/yyyy格式,并使用date进行验证。您可以在if
语句中使用以下表达式:
echo "$1" | egrep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$' && date -d "$(echo "$1" | awk 'BEGIN{FS=OFS="/"}{print $2"/"$1"/"$3}')" >/dev/null 2>&1
'^[0-9]{2}/[0-9]{2}/[0-9]{4}$'
,因为后续使用date
检查将会淘汰像40/01/2020这样的日期。 - Joman68Bash中最简单的获取dd/mm/yyyy
日期格式的方法如下:
if [[ $1 == [0-3][0-9]/[0-1][0-9]/[0-9][0-9][0-9][0-9] ]]
或者
if [[ $1 =~ ^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$ ]]
#! /bin/bash
isDateInvalid()
{
DATE="${1}"
# Autorized separator char ['space', '/', '.', '_', '-']
SEPAR="([ \/._-])?"
# Date format day[01..31], month[01,03,05,07,08,10,12], year[1900..2099]
DATE_1="((([123][0]|[012][1-9])|3[1])${SEPAR}(0[13578]|1[02])${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..30], month[04,06,09,11], year[1900..2099]
DATE_2="(([123][0]|[012][1-9])${SEPAR}(0[469]|11)${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..28], month[02], year[1900..2099]
DATE_3="(([12][0]|[01][1-9]|2[1-8])${SEPAR}02${SEPAR}(19|20)[0-9][0-9])"
# Date format day[29], month[02], year[1904..2096]
DATE_4="(29${SEPAR}02${SEPAR}(19|20(0[48]|[2468][048]|[13579][26])))"
# Match the date in the Regex
if ! [[ "${DATE}" =~ "^(${DATE_1}|${DATE_2}|${DATE_3}|${DATE_4})$" ]]
then
echo -e "ERROR - '${DATE}' invalid!"
else
echo "${DATE} is valid"
fi
}
echo
echo "Exp 1: "`isDateInvalid '12/13/3000'`
echo "Exp 2: "`isDateInvalid '12/11/2014'`
echo "Exp 3: "`isDateInvalid '12 01 2000'`
echo "Exp 4: "`isDateInvalid '28-02-2014'`
echo "Exp 5: "`isDateInvalid '12_02_2002'`
echo "Exp 6: "`isDateInvalid '12.10.2099'`
echo "Exp 7: "`isDateInvalid '31/11/2000'`
echo "31/12/1999" | awk -F '/' '{ print ($1 <= 31 && $2 <= 12 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }'
31/02/2012
或29/02/2001
或31/04/2000
等日期... :(
- gniourf_gniourfecho "31/12/1999" | awk -F '/' '{ print ($1 <= 12 && $2 <= 31 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }'
唯一的注意点是,即使这不是一个日期,02/30/2014
也会通过,但这仍然完全符合我的需求。 - JNevill#!/bin/sh
##########
#
# check if date valid in busybox
# tested in busybox 1.29.3, 1.23.1
#
# call with:
# $0 <yyyymmdd>
#
##########
mydate=$1
if echo $mydate | grep -qE '20[0-9][0-9](0[1-9]|1[0-2])([012][0-9]|3[01])'; then
printf 'may be valid\n'
date +%Y%m%d -d $mydate -D %Y%m%d > /dev/null 2>&1
is_valid=$?
if [ $is_valid -ne 0 ]; then
printf 'not valid\n'
return 1
else
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
printf 'not valid, results in "%s"\n' "$mytestdate"
return 1
else
printf 'valid\n'
fi
fi
else
printf 'not valid (must be: <yyyymmdd>)\n'
return 1
fi
就像在busybox(1.29.3和1.23.1)中一样,您会得到如下响应:
lxsys:~# date +%Y%m%d -d 20110229 -D "%Y%m%d"
20110301
我需要以更好的方式验证日期,但我希望主要依赖于系统本身。
因此使用
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
...
fi
这里有第二个测试 - 我们是否在期望格式(输入,$mydate
)和系统解释(输出,$mytestdate
)之间有差异... 如果不同,则丢弃该日期。
# Script expecting a Date parameter in MM-DD-YYYY format as input
verifyInputDate(){
echo ${date} | grep '^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$'
if [ $? -eq 0 ]; then
echo "Date is valid"
else
echo "Date is not valid"
fi
}
99/87/0000
这样的日期也会通过你的 grep。 - JNevillecho $x | cut -c 6-7
echo $x | cut -c 1-4
2>/dev/null | grep -c echo $x | cut -c 9-10
如果该值为1,则有效,否则无效。