14

我必须创建一个 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 格式?

4

13 回答 13

26

使用日期

date "+%d/%m/%Y" -d "09/99/2013" > /dev/null  2>&1
 is_valid=$?

日期字符串必须采用“MM/DD/YYYY”格式。

如果您没有得到 0,则日期格式无效。

于 2013-09-11T01:49:31.217 回答
20

最简单的解决方案仍然可以完美运行,如下所示:

if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1
   ...

它包括结合2个检查:

  • 第一部分检查$1是这种格式:NNNN-NN-NN
  • 第二部分检查它是否是有效日期

您需要这两项检查,因为:

  • 如果您不进行第一次检查,date即使您的变量是另一种格式的有效日期,也会以代码 0 退出
  • 如果您不进行第二次检查,那么即使对于变量,例如2016-13-45
于 2016-05-10T16:32:26.083 回答
5

此函数需要 2 个字符串,一个格式字符串,一个日期字符串

格式字符串使用 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
于 2018-05-04T05:38:43.503 回答
3

首先,使用正则表达式检查输入的形式。然后使用 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
于 2013-09-11T04:50:24.510 回答
3

dd/mm/yyyy在 Bash 中最简单的方法是:

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}$ ]]
于 2013-09-11T08:18:10.827 回答
2

如何使用awk

echo "31/12/1999" | awk  -F '/' '{ print ($1 <= 31 && $2 <= 12 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }'

如果其有效日期打印“好”,否则打印“坏”

于 2013-10-31T15:45:15.370 回答
2
#! /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'`
于 2014-03-18T11:37:44.263 回答
1

这是一个执行一些数据验证的函数:

# 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
}
于 2013-12-19T16:15:13.727 回答
1

`X="2016-04-21" 然后检查以下值是否为 1 或 0。

cal echo $x | cut -c 6-7 echo $x | cut -c 1-42>/dev/null | grep -cecho $x | cut -c 9-10

如果值为 1,那么它是有效的,否则它是无效的。

于 2016-04-21T15:50:14.297 回答
1

虽然解决方案(如果 [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev @ https://stackoverflow.com/users/2873507/vic-seedoubleyew的/null 2>&1)至少对于 linux 来说是最好的,但它会给出错误,因为我们不能在 if 语句中直接比较/匹配正则表达式。我们应该将正则表达式放在一个变量中,然后我们应该在 if 语句中比较/匹配该变量。此外,if 条件的第二部分不返回布尔值,因此这部分也会导致错误。

所以我对上面的公式做了一些修改,这个修改也可以进一步定制为各种其他格式或它们的组合。

DATEVALUE=2019-11-12
REGEX='^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
if [[ $DATEVALUE =~ $REGEX ]] ; then
    date -d $DATEVALUE 
  if [ $? -eq 0 ] ; then
    echo "RIGHT DATE"
   else 
    echo "WRONG DATE"
  fi
else
 echo "WRONG FORMAT"
fi
于 2019-07-29T15:39:13.197 回答
0

我编写了这个 bash 脚本来验证日期。我可以接受 mont 作为字母数字。

#!/bin/bash

function isDateValid {
    DATE=$1

    if [[ $DATE =~ ^[0-9]{1,2}-[0-9a-zA-Z]{1,3}-[0-9]{4}$ ]]; then
        echo "Date $DATE is a number!"
        day=`echo $DATE | cut -d'-' -f1`
        month=`echo $DATE | cut -d'-' -f2`
        year=`echo $DATE | cut -d'-' -f3`

                if [ "$month" == "01" ] || [ "$month" == "1" ]; then
                        month="Jan"
                elif [ "$month" == "02" ] || [ "$month" == "2" ]; then
                        month="Feb"
                elif [ "$month" == "03" ] || [ "$month" == "3" ]; then
                        month="Mar"
                elif [ "$month" == "04" ] || [ "$month" == "4" ]; then
                        month="Apr"
                elif [ "$month" == "05" ] || [ "$month" == "5" ]; then
                        month="May"
                elif [ "$month" == "06" ] || [ "$month" == "6" ]; then
                        month="Jun"
                elif [ "$month" == "07" ] || [ "$month" == "7" ]; then
                        month="Jul"
                elif [ "$month" == "08" ] || [ "$month" == "8" ]; then
                        month="Aug"
                elif [ "$month" == "09" ] || [ "$month" == "9" ]; then
                        month="Sep"
                elif [ "$month" == "10" ]; then
                        month="Oct"
                elif [ "$month" == "11" ]; then
                        month="Nov"
                elif [ "$month" == "12" ]; then
                        month="Dec"
                fi

        ymd=$year"-"$month"-"$day
        echo "ymd: "$ymd
        dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }')
        echo "dmy: "$dmy
        if date --date "$dmy" >/dev/null 2>&1; then
                echo "OK"
            return 0
        else
                echo "NOK"
            return 1
        fi
    else
        echo "Date $DATE is not a number"
        return 1
    fi
}


if isDateValid "15-15-2014"; then
    echo "date is valid =)"
else
    echo "bad format date"
fi
echo "==================="
if isDateValid "15-12-2014"; then
        echo "date is valid =)"
else
        echo "bad format date"
fi
echo "==================="
if isDateValid "15-Dec-2014"; then
        echo "date is valid =)"
else
        echo "bad format date"
fi
echo "==================="
if isDateValid "1-May-2014"; then
        echo "date is valid =)"
else
        echo "bad format date"
fi
echo "==================="
if isDateValid "1-1-2014"; then
        echo "date is valid =)"
else
        echo "bad format date"
fi
echo "==================="
if isDateValid "12-12-2014"; then
        echo "date is valid =)"
else
        echo "bad format date"
fi
于 2017-07-20T09:25:39.393 回答
0

我想给出一个稍微不同的格式的扩展答案,但这可以很容易地更改为 dd/mm/YY 格式,并且已经给出了答案;它在busybox(posix shell)上进行了测试

这是类似于“busybox posix shell 脚本日期”和“测试格式”或“验证”等的网络搜索的第一个热门,所以这里是我的busybox 解决方案(使用 1.29.3、1.23.1 测试)

#!/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 != 0 ]; then
        printf 'not valid\n'
        return 1
    else
        mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
        if [ $mydate != $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 != $mytestdate ]; then
    ...
fi

还有第二个测试 - 我们想要或给定的格式(输入,$mydate)和它的系统解释(输出,$mytestdate)之间是否有区别......如果它不一样,丢弃日期

于 2021-11-09T18:27:07.657 回答
-2

块引用

DATE = "$*"

[[ "${DATE}" != @(((([123][0]|[012][1-9])|3[1])?([ \/._-])(0[13578]|1[02])?([ \/._-])(19|20)[0-9][0-9])|(([123][0]|[012][1-9])?([ \/._-])\
(0[469]|11)?([ \/._-])(19|20)[0-9][0-9])|(([12][0]|[01][1-9]|2[1-8])?([ \/._-])02?([ \/._-])(19|20)[0-9][0-9])|(29?([ \/._-])02?([ \/._-])\
(19|20(0[48]|[2468][048]|[13579][26])))) ]] && echo error || echo good)
于 2014-03-18T06:28:55.303 回答