Bash에서 날짜 형식 확인

Bash에서 날짜 형식 확인

Bash 스크립트에 다음 줄이 있습니다.

 while true; do
    DATE=date
    FORMAT="%Y%m%d"
    read -p "Enter start date (YYYYMMDD)  " STARTDATE
    if date=$(date -d "$STARTDATE" +'+%Y%m%d'); then
       start_date=`$DATE +$FORMAT -d $STARTDATE`
       echo $start_date
       break
    fi
    echo "Please use right format (YYYYMMDD)  "
 done

이 방법은 입력이 8개의 숫자인 한 잘 작동합니다(예: "20210901"을 허용하고 "20213131"을 거부). 그러나 입력이 완전히 꺼져 있으면(예: "a" 또는 "nonsense") 오늘 날짜만 필요합니다. 형식을 보다 엄격하게 확인하려면 코드를 어떻게 수정해야 합니까?

수정된 코드는 다음과 같습니다.

 valid=0
 while true; do
    DATE=date
    FORMAT="%Y%m%d"
    read -p "Enter start date (YYYYMMDD)  " initialdate
    if date=$(date -d "$initialdate" +'+%Y%m%d'); then
       start_date=`$DATE +$FORMAT -d $initialdate`
       if [[ "$start_date" =~ ^[[0123456789]]{8}$ ]]
       then
         valid=1 
         echo "valid"; 
         echo $start_date
         break
       else
         echo "Invalid format" 
       fi
    fi
    echo "Please use right format (YYYYMMDD)  "
 done

답변1

입력 유효성 검사를 수행하는 일반적인 방법은 입력 유효성이 검사되면 중단할 수 있는 무한 루프를 사용하는 것입니다.

이 경우 "검증됨"은 입력 문자열에 8자리 숫자만 포함되어 있고 GNU가 해당 날짜를 옵션에 대한 옵션 인수 date로 사용할 수 있음 을 의미합니다.-d

그걸로 bash우리는 다음과 같이 쓸 수 있습니다.

while true; do
    read -r -p 'Input date: '

    if [[ $REPLY =~ ^[[:digit:]]{8}$ ]] && date -d "$REPLY" >/dev/null 2>&1
    then
        break
    fi

    echo 'Invalid format, try again' >&2
done

thedate=$REPLY

이는 루프 시작 부분에서 날짜를 읽은 다음 문자열에 8자리만 포함된 경우 일치하는 정규식을 사용하여 테스트합니다. 테스트가 통과하면 문자열도 GNU를 사용하여 테스트됩니다 date. 모든 것이 순조롭게 진행되면 루프는 break명령문을 통해 종료됩니다.

에서는 sh정규식 일치를 셸 패턴 일치로 바꿔야 합니다.

while true; do
    printf 'Input date: ' >&2
    read -r REPLY

    case $REPLY in
        *[![:digit:]]*)
            ;;
        ????????)
            date -d "$REPLY" >/dev/null 2>&1 && break
    esac

    echo 'Invalid format, try again' >&2
done

thedate=$REPLY

여기서 테스트는 먼저 문자열에 숫자 이외의 문자가 포함되어 있는지 테스트합니다. 해당 테스트가 실패하면 다음 테스트는 정확히 8자입니다. 테스트가 성공하면 GNU를 사용하여 테스트하는 8자리 문자열을 얻고 date날짜가 정확하면 루프를 종료합니다.

답변2

입력에 정확히 8자리 숫자가 포함되어야 하는지 확인하는 추가 검사로 작업을 줄일 수 있고 Bash를 사용하고 있으므로 정규식 비교 연산자를 활용할 수 있습니다.

if [[ "$startdate" =~ ^[0123456789]{8}$ ]]; then echo "valid"; else echo "invalid"; fi

이는 내용이 $startdate정확히 8자리 숫자로 구성된 정규식과 일치하는지 확인합니다.

다음과 같이 결합할 수 있습니다.

valid=0
while (( valid == 0 )); do
    valid=1
    IFS= read -r -p "Enter start date (YYYYMMDD): " startdate

    if [[ ! "$startdate" =~ ^[0123456789]{8}$ ]]; then valid=0;
    elif ! date -d "$startdate" +%Y%m%d > /dev/null 2>&1 ; then valid=0; fi

    if (( valid == 0 )); then printf "Invalid date entered\n"; fi
done

# < ... operations for valid date here ... >

기본 규칙은 다음과 같습니다.

  • 권장 용도shellcheck는 쉘 스크립트를 확인하기 위해 많은 Linux 배포판에서 독립 실행형 프로그램으로도 사용할 수 있습니다.
  • $PATH실수로 중요한 설정을 덮어쓰는 것을 방지하기 위해 변수 이름을 환경 변수로 내보내려는 경우가 아니면 변수 이름을 모두 대문자로 사용하는 것은 권장되지 않습니다 .

답변3

또는 무한 루프 없이 BSD date(1)명령을 가정합니다.

REPLY=
valid=false

while ! $valid; do

    read -r -p 'Input date: '

    if ([[ $REPLY =~ ^[[:digit:]]{8}$ ]]) && (date -j +%Y%m%d ${REPLY}0000 >/dev/null 2>&1)
    then
        valid=true
    else
        echo 'Invalid format, try again' >&2
    fi

done

thedate=$REPLY

BSD에는 전체 YmdHM이 필요하지만 기본 HM이면 충분하므로 이 ${REPLY}0000구문이 필요합니다 .date0000

관련 정보