정규 표현식은 문자가 아닌 밑줄 뒤에 숫자가 있는지 확인합니다.

정규 표현식은 문자가 아닌 밑줄 뒤에 숫자가 있는지 확인합니다.

테이블 이름에 정수가 포함되어 있는지 확인하는 쉘 스크립트에 if 루프가 있습니다. 이것이 제가 지정한 조건입니다.

if [[ "$able_name" == *[0-9]* ]] 

일반적으로 테이블 이름은 다음과 같습니다.

tablename_000 

또는

tablename_001 

하지만 이름이 정규식과 일치하므로 이 루프로 들어가는 새 파일이 있습니다 table_V2. 이것을 어떻게 피할 수 있습니까? if밑줄 뒤에 정수가 있고 다른 문자가 없는 경우에만 루프에 들어가야 합니다.

답변1

표준 sh구문을 사용하십시오.

case ${table_name##*_} in
  ("$table_name" | "" | *[!0-9]*) echo >&2 incorrect;;
  (*) echo correct;;
esac

즉, 검사는 $table_name맨 오른쪽에 있는 자체(아무것도 의미하지 않음 ) _도 아니고 빈 문자열도 아니고 숫자가 아닌 문자를 포함하는 모든 것을 제거합니다.$table_name$table_name_

문자열을 정규식과 일치시키는 표준 명령 expr에는 몇 가지 문제가 있으며 코드가 명확하지 않습니다.

if expr " $table_name" : '.*_[0-9]\{1,\}$' > /dev/null; then
  echo Correct
else
  echo >&2 Incorrect
fi

선행 공백은 $table_namelike +또는 의 값에 문제가 발생하지 않도록 하기 위한 것입니다 --help. 정규식은 암시적으로 시작 부분( is .*)에 고정되지만 끝( is $)에는 고정되지 않으며 결과(여기서는 0 또는 1)가 종료 상태에 반영되는 것 외에도 stdout에 출력되므로 /로 리디렉션됩니다. 개발/널.

내장 합계 [와 같은 일부 구현에는 연산자 가 있습니다 (ERE를 사용하지만 다음을 사용 하여 PCRE로 변경할 수 있음).[zshyash=~zsh

if [ "$table_name" '=~' '_[0-9]+$' ]; then
   echo Correct
else
   echo >&2 Incorrect
fi

bash, 참조의 구문과 동작은 구현마다 다르지만 zsh그 안에 ksh93연산자 연산자가 있습니다 . =~[[...]]변수를 사용하는 것이 더 좋습니다@BLayer에서 볼 수 있듯이

zsh -o extendedgloband ksh( bash -O extglob또는 zsh -o kshglobglob 하위 집합 지원 ksh)에는 구문은 다르지만 기능적으로 정규식과 동일한 glob 연산자가 있습니다.

번역 RE -> ksh-glob/zsh-glob:

  • [0-9]-> [0-9]/[0-9]
  • x+-> +(x)/x##
  • $또는 ^-> 암시적/암시적
  • .->?
  • .*-> *(또는 *(?))/ *(또는 ?#)

따라서 ksh(또는 bash -O extglob또는 zsh -o kshglob)에서는:

case $table_name in
  (*_+([0-9]) echo correct;;
  (*) echo >&2 incorrect;;
esac

존재하다 zsh -o extendedglob:

case $table_name in
  (*_[0-9]##) echo correct;;
  (*) echo >&2 incorrect;;
esac

zsh에서 까지의 십진수를 <x-y>일치시키는 확장된 glob 연산자 도 있으므로 이를 작성할 수도 있습니다 .xy(*_<->) echo correct

=이러한 쉘에서 이러한 glob은 aka 연산자의 오른쪽에서도 사용할 수 있습니다 == [[...]].

답변2

아마도 가장 간단한 정규식은 다음과 같습니다.

if [[ "$file" =~ _[0-9]+$ ]]
then
    echo OK $file
fi

답변3

이를 수행하는 방법에는 여러 가지가 있습니다. 다음은 전통적인 정규식의 Bash 버전입니다(또는 적어도 Bash가 가지고 있는 것과 가장 가까운 것):

pattern='^tablename_[[:digit:]]+$'
if [[ $filename =~ $pattern ]]; then
    echo "Filename $filename is valid"
fi

몇 가지 참고사항:

  • 가장 단순한 정규 표현식을 제외한 모든 경우에는 여기에서 사용하는 것처럼 변수를 사용하는 것이 좋습니다 pattern. 내부 표현식에 단어 분리나 경로 이름 확장이 적용되지 않더라도 [[ ]]물결표, 변수 및 산술 확장과 프로세스 및 명령 대체가 있을 것입니다. 인라인 정규 표현식을 사용하면 부정확하거나 예상치 못한 결과를 얻기 쉽습니다.
  • POSIX 문자 클래스를 사용하고 있지만 [:digit:]그것도 0-9괜찮습니다. 여기의 다른 답변 대부분은 후자를 사용한다고 생각하며 완전성을 위해 전자를 보여줄 가치가 있습니다.

댓글: 이 주제에 대한 변형이 너무 많다는 사실(이 스레드에만 있음)은 sh일부 사람들이 / ...을 좋아하지 않는 이유 중 하나 bash이며 ... 제가 좋아하는 이유 중 하나입니다.:)

답변4

이를 위해 regex 옵션을 사용하는 것이 좋지만 숫자만 포함하는 일반 glob도 사용할 수 있습니다. 예를 들어 다음과 같은 작업을 수행할 수 있습니다.

for file in tablename_[0-9]*; do
    [ -f "$file" ] || continue
    printf "%s\n" "$file"
done

에서 정규식 연산자를 사용하면 bash다음과 같은 작업을 수행할 수 있습니다.

for file in tablename_*; do
    if [[ $file =~ _([[:digit:]]+)$ ]]; then
        printf "%s\n" "$file"
    fi
done

관련 정보