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

または、無限ループなしでBSDdate(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

関連情報