Проверка формата даты в оболочке script

Мне нужно создать оболочку Script, в которой одним из параметров будет дата в формате dd/mm/yyyy. Мой вопрос: как я могу проверить, действительно ли Date, прошедший как параметр, соответствует этому формату даты? Я попытался использовать команду grep, как показано ниже:

if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$'

но он не дал правильного формата, потому что день, например, может быть 33, 34, (...), это не совсем правильный формат. Кто-нибудь знает что-то, что действительно может проверить, действительно ли прошедшая дата соответствует формату dd/mm/yyyy?

Ответ 1

Используйте date

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

Если вы не получаете 0, то дата находится в неверном формате.

Ответ 2

Самое простое решение, которое все еще отлично работает, следующее:

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

Он состоит в объединении двух проверок:

  • первая часть проверяет, что $1 имеет этот формат: NNNN-NN-NN
  • вторая часть проверяет, что это действительная дата.

Вам нужны две проверки, потому что:

  • Если вы не сделаете первую проверку, date выйдет с кодом 0, даже если ваша переменная является допустимой датой в другом формате
  • Если вы не сделаете вторую проверку, тогда вы можете получить 0 даже для переменных, таких как 2016-13-45

Ответ 3

Эта функция ожидает 2 строки, строку формата, строку даты

Строка формата использует коды из команды date, но не включает '+'

Функция возвращает 0, если указанная дата соответствует заданному формату, в противном случае она возвращает 1

datecheck() {
    local format="$1" d="$2"
    [[ "$(date "+$format" -d "$d" 2>/dev/null)" == "$d" ]]
}

Ответ 4

Сначала проверьте форму ввода с помощью регулярного выражения. Затем используйте awk для переключения на mm/dd/yyyy и используйте дату для проверки. Вы можете использовать следующее выражение в своем выражении 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

Ответ 5

Самый простой способ для 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}$ ]]

Ответ 6

Как насчет использования awk:

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

Он печатает "хорошо", если его действительная дата еще печатает "плохо"

Ответ 7

#! /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'`

Ответ 8

Здесь функция для проверки некоторых данных:

# 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
}

Ответ 9

`X = "2016-04-21", затем проверьте, что нижеследующее значение равно 1 или 0.

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

Если значение равно 1, оно действительно, иначе оно недействительно.

Ответ 10

Я написал этот bash script для подтверждения даты. Я могу принять 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

Ответ 11

Хотя решение (если [[$ 1 = ~ ^ [0-9] {4} - [0-9] {2} - [0-9] {2} $]] && date -d "$ 1 ">/dev/null 2> & 1) из @https://stackoverflow.com/users/2873507/vic-seedoubleyew лучше всего подходит по крайней мере для 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

Ответ 12

Blockquote

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)