문자열이 숫자인지 테스트

문자열이 숫자인지 테스트

이것은 간단해야 합니다. 단지 [[ "$var" =~ '^[1-9][0-9]*$' ]]. 나는 스크립트가 실행되는 시스템을 제어하지 않으므로 합리적인 쉘(Solaris의 이전 Bourne 쉘은 아님)의 이식성이 문제입니다. 다음은 몇 가지 테스트입니다.

% zsh --version
zsh 4.3.10 (x86_64-redhat-linux-gnu)
% zsh -c "[[ 100 =~ '^[1-9][0-9]*\$' ]] && echo OK"
OK
% sh --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
% sh -c "[[ 100 =~ '^[1-9][0-9]*\$' ]] && echo OK" 
% bash --version
GNU bash, version 4.2.53(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
% bash -c "[[ 100 =~ '^[1-9][0-9]*\$' ]] && echo OK"
% ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01
% ksh -c "[[ 100 =~ '^[1-9][0-9]*\$' ]] && echo OK"
% 

뭔가 빠진 것 같습니다. 무엇?

답변1

문자열이 숫자인지 테스트

이를 위해서는 정규 표현식이 필요하지 않습니다. 문을 사용하여 case문자열을 와일드카드 패턴과 일치시킵니다. 정규식만큼 강력하지는 않지만 여기서는 충분합니다. 바라보다내 정규 표현식이 X에서는 작동하지만 Y에서는 작동하지 않는 이유는 무엇입니까?와일드카드 패턴(글로브)이 정규식 구문과 어떻게 다른지에 대한 요약이 필요한 경우. 이는 모든 sh 구현(POSIX Bourne 이전 버전 포함)에서 작동합니다.

case $var in
  '' | *[!0123456789]*) echo >&2 "This is not a non-negative integer."; exit 2;;
  [!0]*) echo >&2 "This is a positive integer. I like it.";;
  0*[!0]*) echo >&2 "This is a positive integer written with a leading zero. I don't like it."; exit 2;;
  *) echo >&2 "This number is zero. I don't like it."; exit 2;;
esac

케이스 휴대성

모든 Unix 시스템에는 sh가 구현되어 있습니다. 골동품이 아닌 Unix 또는 POSIX 시스템에는 (대부분) 다음과 같은 sh 구현이 있습니다.POSIX 사양. 일반적으로 Linux에 있지만 고대 Bourne 쉘과 최신 POSIX sh 등 /bin/sh일부 상업용 유니스도 있습니다./bin/sh/usr/posix/bin/sh

그것이 당신에게 적합하지 않다면 #!/usr/bin/env sh실용적인 휴대용 코드로 사용할 수 있습니다.#!/bin/sh

[[ … ]]POSIX sh에서는 사용할 수 없습니다. ksh93, mksh, bash 및 zsh에서는 사용할 수 있지만 /bin/shdash(Linux에서 인기 있음) 또는 BusyBox(임베디드 Linux에서 인기 있음)에서는 사용할 수 없습니다. /bin/shPortable sh에는 내장된 정규식 일치가 없고 와일드카드 일치만 있습니다. grep, awk 또는 sed를 사용하여 POSIX 시스템에서 정규식 일치 항목을 얻을 수 있습니다.

정규식 인용=~

=~Ksh93, bash 및 zsh에는 조건식에 정규식 일치 연산자가 있습니다 [[ … ]]. 인용 규칙은 약간 다릅니다.

=~Bash ≥3.1에서 정규식 문자는 따옴표가 없는 경우에만 연산자 오른쪽에 특수 효과가 있습니다. so [[ 100 =~ ^[1-9][0-9]*$ ]]는 true이지만 [[ 100 =~ '^[1-9][0-9]*$' ]]false입니다( 하위 문자열이 있는 문자열 [[ $x =~ '^[1-9][0-9]*$' ]]만 일치 ).^[1-9][0-9]*$

ksh 93u에서 정규 표현식에서 문자를 인용하는 효과는 문자에 따라 다릅니다. 와일드카드이기도 한 문자는 인용하면 안 되지만, 그렇지 않은 문자는 작은따옴표나 큰따옴표를 사용하여 인용할 수 있습니다(그러나 앞에 백슬래시가 올 수는 없습니다). so [[ 100 =~ ^[1-9][0-9]*$ ]]는 true이고, so는 false [[ 100 =~ '^'[1-9][0-9]*'$' ]]이지만 [[ 100 =~ '^[1-9][0-9]*$' ]](하위 문자열이 있는 모든 항목과 일치 [1-9][0-9]*) [[ 100 =~ ^[1-9][0-9]*\$ ]]거짓이기도 합니다(0이 아닌 숫자로 시작하고 더 많은 숫자와 a로 시작하는 모든 문자열과 일치 $).

zsh에서는 모든 정규식 문자를 따옴표로 묶거나 따옴표를 해제할 수 있습니다. 이는 문자 그대로 문자를 포함하려면 별표와 일치하는 \\*또는 와 같은 2단계 참조가 필요함을 의미합니다 . '\*'그래서 및 [[ 100 =~ ^[1-9][0-9]*$ ]]둘 다 [[ 100 =~ '^[1-9][0-9]*$' ]]정확합니다.

정규식을 변수에 넣는 것이 쉘 기능에 의존하지 않는 가장 안정적인 방법이라고 생각합니다.

regex='…' # Use extended regular expression syntax here, with '\'' if you need a literal apostrophe
if [[ $string =~ $regex ]]; …

정규식/와일드카드 대괄호 표현식의 범위

일치 범위는 [0-9]구현 및 로케일에 따라 다릅니다. 일반적으로 말해서 0123456789만 일치할 것이라고 기대할 수는 없습니다. (물론 일치할 것이라고 가정할 수는 있지만)적어도그것들). 0123456789만 일치시키는 것이 중요한 경우에는 범위 사용을 피하고 문자 이름을 개별적으로 지정하세요.

관련 정보