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