日付パターンを一致させるためにコマンドを使用しようとしましたが、case機能しません。誰でも私を助けることができますか?

入力する01/05/1900 または5/6/1900

使用されたケースの説明:

ptn="[0-9]|[0-9][0-9]/[0-9]|[0-9][0-9]/[0-9][0-9]|[0-9][0-9][0-9][0-9]"

case "$dt" in 
    $ptn ) echo "valid pattern" ;;
    *) echo "invalid"
esac

ただし、Caseステートメントで使用されているパターンは、上記の2つの日付入力を評価しません。

答え1

この試み。 caseグローバル変数だけが理解されるため、正規表現を扱うのは簡単ではありません。しかし、キャリアは=~ここにいくつかの解決策を持っています。

#!/bin/bash
INP="01/05/1900"
ptn="^([0-9]|[0-9][0-9])/([0-9]|[0-9][0-9])/([0-9][0-9]|[0-9][0-9][0-9][0-9])$"
if [[ $INP =~ $ptn ]] ; then
    echo valid pattern
else
    echo invalid
fi

正規表現のサイズを小さくしたい場合も^[0-9]{1,2}/[0-9]{1,2}/([0-9]{2}|[0-9]{4})$同様です。

答え2

@Steveのように言及するcase正規表現ではなくglobが必要です。それでも使用できますcase。ただglobだけでいいです。

#!/bin/sh
dt="$1";
ptn1="[0-9]/[0-9]/[0-9][0-9][0-9][0-9]"           ## N/N/NNNN
ptn2="[0-9][0-9]/[0-9]/[0-9][0-9][0-9][0-9]"      ## NN/N/NNNN
ptn3="[0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]"      ## N/NN/NNNN
ptn4="[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]" ## NN/NN/NNNN

case "$dt" in 
    $ptn1|$pt2|$pt3|$pt4 ) echo "$dt : valid pattern" ;;
    *) echo "$dt : invalid" ;;
esac

次に、次のようにスクリプトを実行します。

foo.sh 15/6/1900

たとえば、

$ for i in 05/6/1900 5/06/1900 05/06/1900 05/06/19 123/123/123; do foo.sh $i; done
05/6/1900 : valid pattern
5/06/1900 : valid pattern
05/06/1900 : valid pattern
05/06/19 : invalid
123/123/123 : invalid

GNUツール(特にGNU date)にアクセスできる場合は、次の方法を使用することもできます。

#!/bin/sh
dt="$1";
date -d $dt &> /dev/null &&
        echo "$dt : Valid pattern" ||
                echo "$dt :Invalid pattern"

次に、前と同じテスト入力で次の操作を行います。

$ for i in 05/6/1900 5/06/1900 05/06/1900 05/06/19 123/123/123; do foo.sh $i; done
05/6/1900 : Valid pattern
5/06/1900 : Valid pattern
05/06/1900 : Valid pattern
05/06/19 : Valid pattern
123/123/123 :Invalid pattern

ご覧のとおり、この方法では、年が代わりに指定されている場合でも、より効率的なYYパターンを得ることができますYYYY

答え3

あなたが提示する「パターン」:

ptn="[0-9]|[0-9][0-9]/[0-9]|[0-9][0-9]/[0-9][0-9]|[0-9][0-9][0-9][0-9]"

基本パターン

ケースで使用されるデフォルトモードには適用されません。デフォルトモードでは許可されていません|。計算{a,b}(man 7正規表現では「バインド」と呼ばれる)も許可されていません。ステートメントで機能させるには、case各パターンを明示的に作成する必要があります。

ptn1="[0-9]/[0-9]/[0-9][0-9]"                       # n  / n  / nn
ptn2="[0-9]/[0-9]/[0-9][0-9][0-9][0-9]"             # n  / n  / nnnn
ptn3="[0-9]/[0-9][0-9]/[0-9][0-9]"                  # n  / nn / nn
ptn4="[0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]"        # n  / nn / nnnn
ptn5="[0-9][0-9]/[0-9]/[0-9][0-9]"                  # nn / n  / nn
ptn6="[0-9][0-9]/[0-9]/[0-9][0-9][0-9][0-9]"        # nn / n  / nnnn
ptn7="[0-9][0-9]/[0-9][0-9]/[0-9][0-9]"             # nn / nn / nn
ptn8="[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]"   # nn / nn / nnnn

次に、次のように使用します。

case $dt in 
    $ptn1|$ptn2|$ptn3|$ptn4|$ptn5|$ptn6|$ptn7|$ptn8 )
        echo "$dt : valid pattern" ;;
    *)  
        echo "$dt : invalid" ;;
esac

(シェル)拡張モード.

一部のシェルでは拡張モードが可能です。
これをkshではパターンリストと呼び、bashでは拡張パターン(extglob)と呼びます。

#!/usr/bin/ksh
ptn="{2}({1,2}([0-9])/){2,4}([0-9])" 
while read dt; do
    printf 'line tested %20s ' "$dt"
    [[ $dt == $ptn ]] && echo "valid pattern" ||  echo "invalid"
done <"infile"

正規表現

ただし、提供されたパターンは、次のより単純な(BRE)正規表現に縮小できます。

([0-9]{1,2}/){2}[0-9]{2,4}

これは:

  • 1桁または2桁の数字の後に/:[0-9]{1,2}/
  • 上記を2回繰り返します。 ( ){2}
  • 2~4桁の数字を追加: [0-9]{2,4}

#!/bin/bash
# also works in ksh and zsh.
reg="^([0-9]{1,2}/){2}[0-9]{2,4}$"

while read dt; do
    printf 'line tested %20s ' "$dt"
    [[ $dt =~ $reg ]] && echo "valid pattern" ||  echo "invalid"
done <"infile"

BRE正規表現。

ksh、bash、またはzshを使用できない場合は、正規表現の周りにバックティックを入れてください。

reg="^\([0-9]\{1,2\}/\)\{2\}[0-9]\{2,4\}$"

そして使用してくださいexpr(例:sedとawkも使用できます):

reg="^\([0-9]\{1,2\}/\)\{2\}[0-9]\{2,4\}$"

while read dt; do
    printf 'line tested %20s ' "$dt"
    expr "$dt" : "\($reg\)" >/dev/null && echo "valid pattern" ||  echo "invalid"
done <"infile"

答え4

私はTerdenの答えが好きです。

~について正規表現問題の一部は、スキーマが無効であることです。\次のようにすべての特殊文字をエスケープする必要があります。

([0-9]|[0-9][0-9])\/([0-9]|[0-9][0-9])\/([0-9][0-9]|[0-9][0-9][0-9][0-9])

日付などの既知のデータセットの場合、インターネット上の日付一致に対する回答は文字通り何千ものあるため、車輪を再作成しようとしないでください。よりパーソナライズされたコンテンツを作成したい場合は、私が個人的に好きな正規表現ヘルパーを使用してください。regex.com必要に応じてパターンをテストして強化します。

編集する:01/01/2016エスケープ文字を使用すると、コードはいくつかの日付をキャプチャしますが、キャプチャせずに 。キャプチャだけなので、まだ完璧ではありません01/01/20。年の「優先順位」は4ではなく2つの数字です。最初に最大の一致を見つけるには切り替える必要があります。失敗した場合は、最小の一致をキャプチャします。

([0-9]|[0-9][0-9])\/([0-9]|[0-9][0-9])\/([0-9][0-9][0-9][0-9]|[0-9][0-9])

関連情報