日付パターンを一致させるためにコマンドを使用しようとしましたが、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])