날짜 패턴을 일치시키기 위해 명령을 사용하려고 시도했지만 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}

이것은:

  • 한 자리 또는 두 자리 숫자 뒤에 /: [0-9]{1,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])

관련 정보