2013-09-11 42 views
8

Tôi phải tạo Tập lệnh Shell trong đó một trong các tham số sẽ là ngày theo định dạng dd/mm/yyyy. Câu hỏi của tôi là, làm cách nào tôi có thể kiểm tra xem thông số Ngày được truyền dưới dạng thực sự có tuân theo Định dạng ngày này không? Tôi cố gắng để sử dụng lệnh grep như sau:Xác thực định dạng ngày trong tập lệnh shell

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

nhưng nó đã không đưa ra định dạng đúng vì ngày, ví dụ có thể là 33, 34 tuổi, (...), đó không phải là thực sự đúng định dạng . Bất cứ ai biết một cái gì đó mà thực sự có thể kiểm tra xem ngày trôi qua thực sự theo định dạng dd/mm/yyyy?

+0

Xem thêm http://unix.stackexchange.com/a/236374/106927 –

Trả lời

19

Sử dụng date

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

Nếu bạn không nhận được 0 thì ngày là ở định dạng không hợp lệ.

+0

Cảm ơn câu trả lời của bạn. Điều này thực sự hiệu quả nhưng chỉ dành cho định dạng dd/mm/yyyy. Nếu bạn kiểm tra trên thiết bị đầu cuối tùy chọn -d kiểm tra chỉ định dạng mm/dd/yyyy. Tôi đã cố gắng thay đổi định dạng nhưng nó không ảnh hưởng đến cách thức tùy chọn -d cho lệnh ngày được sử dụng. –

+4

WTF? Câu hỏi đặt ra là '' làm cách nào tôi có thể kiểm tra xem thông số Ngày được truyền có thực sự theo định dạng ngày tháng này'' hay không. Điều này không kiểm tra bất cứ điều gì. '' date'' chấp nhận ngày ở các định dạng khác nhau. Ví dụ '' ngày mai'' là một định dạng hợp lệ, '' date -d 'ngày mai + 5 tháng 20: 00: 01'' cũng hợp lệ. –

+0

Ngoài ra '' date -d '05/20/1900''' ném một lỗi cho tôi. Nó cũng phụ thuộc vào kiến ​​trúc của bạn (phạm vi ngày có thể lớn hơn đối với các hệ thống 64 bit). Điều này chắc chắn không phải là con đường để đi. Thay vào đó, hãy sử dụng câu trả lời của [konsolebox] (http://stackoverflow.com/a/18736035/2698019). –

2

Trước tiên, hãy kiểm tra biểu mẫu đầu vào bằng cách sử dụng regex. Sau đó, sử dụng awk để chuyển sang mm/dd/yyyy và sử dụng ngày để xác thực. Bạn có thể sử dụng các biểu thức sau đây trong if tuyên bố của bạn:

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 
2

Cách đơn giản nhất cho dd/mm/yyyy chính xác trong Bash là:

if [[ $1 == [0-3][0-9]/[0-1][0-9]/[0-9][0-9][0-9][0-9] ]] 

Hoặc

if [[ $1 =~ ^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$ ]] 
+0

Đó chính xác là những gì OP đã nói _didn't_ work Bởi vì nó chấp nhận những ngày không hợp lệ như 33/19/2000. – augurar

+0

@augurar Vâng, tôi có thể làm một cách chính xác hơn, nhưng sau đó, ngay cả giải pháp được chấp nhận cũng có thể chấp nhận các định dạng khác không chỉ là «dd/mm/yyyy'. – konsolebox

2

Làm thế nào về việc sử dụng awk:

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

It in "tốt" nếu hợp lệ ngày khác in "xấu" của nó

+0

Điều này sẽ xác thực các ngày như '31/02/2012' hoặc' 29/02/2001' hoặc '31/04/2000' hoặc ...': (' –

+0

Tôi có nhu cầu để xác thực nhiều định dạng ngày trên nhiều tệp, mà tôi đã sẵn sàng để có được ngày tháng. Giải pháp này phù hợp với yêu cầu tốt hơn so với KonsoleBox hoặc của PxL. mũ được nói, định dạng của ngày trong yêu cầu là khác nhau thì giải pháp này. Nó phải là 'echo '31/12/1999" | awk -F '/' '{print ($ 1 <= 12 && $ 2 <= 31 && đối sánh ($ 3,/^ [1-9] [1-9] [1-9] [1-9] $ /)) ? "tốt": "xấu"} '' Thông báo trước duy nhất là' 02/30/2014' sẽ vượt qua mặc dù đó không phải là ngày, nhưng điều này vẫn hoàn hảo cho nhu cầu của tôi. – JNevill

1

Dưới đây là một chức năng để làm một số xác nhận dữ liệu này:

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

Điều này không tốt hơn ví dụ OP. Các ngày như '99/87/0000' sẽ vượt qua grep của bạn. – JNevill

-1

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) 
+0

hi, tại sao bạn thêm ')' sau 'echo good'? – chelabim

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'` 
1

' X = "2016-04-21" sau đó kiểm tra giá trị dưới đây bằng 1 hoặc 0.

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

Nếu giá trị là 1, thì giá trị hợp lệ, nếu không giá trị không hợp lệ.

+0

Bạn có nghĩa là "backticks" không? Bạn nên nhập chúng như vậy trong câu trả lời của bạn sau đó, nếu không nó sẽ không hoạt động vì tại thời điểm chúng * là * dấu nháy đơn. –

8

Giải pháp đơn giản nhất, mà vẫn hoạt động hoàn hảo, như sau:

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

Nó bao gồm trong việc kết hợp 2 kiểm tra:

  • kiểm tra phần đầu tiên mà $1 là của định dạng này: NNNN-NN-NN
  • phần thứ hai kiểm tra xem đó có phải là ngày hợp lệ không

Bạn cần hai kiểm tra bởi vì:

  • nếu bạn không làm việc kiểm tra đầu tiên, date sẽ thoát với mã 0 ngay cả khi biến của bạn là một ngày hợp lệ trong một định dạng
  • nếu bạn don không thực hiện lần kiểm tra thứ hai, sau đó bạn có thể kết thúc bằng 0 ngay cả đối với các biến như 2016-13-45
0

Tôi đã viết tập lệnh bash này để xác thực ngày. Tôi có thể chấp nhận mont là chữ và số.

#!/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 
Các vấn đề liên quan