입력의 유효성을 검사하기 위해 쉘 스크립트에서 어떤 정규식 방법을 사용할 수 있습니까?

입력의 유효성을 검사하기 위해 쉘 스크립트에서 어떤 정규식 방법을 사용할 수 있습니까?
#!/bin/sh

re="\/$"

if [ $1 =~ $re ]; then
        echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
        exit 1
fi

실행 ./file.sh hello/결과는[: 29: hello: unexpected operator

쉘 스크립트에서는 이 정규식 접근 방식이 잘못된 것 같습니다.

답변1

표준 명령은 연산자 없이 test호출될 수도 있습니다 . 이제 대부분의 쉘에는 이 명령이 내장되어 있습니다.[=~

Korn 쉘은 [[...]]대체 구문과 다른 구문 분석 규칙을 사용하여 구문(명령이 아님)을 도입합니다.[[

zshbash어느 정도 복제하지만 제한 사항과 많은 차이점이 있지만 표준화되지 않았으므로 이식 가능한 스크립트에 사용해서는 안 됩니다 sh.

ksh93확장 정규식을 와일드카드 대응으로 변환하는 방법은 항상 있습니다.

pattern=${ printf %P "regexp"; }

그러면 다음과 같이 할 수 있습니다:

[[ $var = $pattern ]]

후에(2001 ksh93l~(E)regex) 또한 확장 정규식 구문 과 마찬가지로 glob에 정규식을 통합하므로 다음을 수행할 수 있습니다.

[[ $var = ~(E)regex ]]

이 패턴 일치는 명령 이 아닌 [[...]]생성자 에서만 작동합니다 .case[

zsh[정규식 일치 연산자가 해당 명령에 추가되었으며 [[...]]2001년에 모듈과 함께 처음 사용되었습니다 pcre. 구문은 원래 [ string -pcre-match regex ]또는 입니다 [[ string -pcre-match regex ]].

bash=~bash 3.0에 연산자가 추가되었습니다.(2004년). 확장 정규식을 사용하세요. ksh93과 zsh는 이것을 곧 추가했습니다(동일한 차이점이 있음).

ksh93그리고bash-3.2~ 위에(해당 compat31옵션이 활성화되지 않은 경우) 따옴표를 사용하세요.탈출하다정규식 연산자는 모든 종류의 혼란을 야기합니다(ksh93에서는 버그가 많았습니다). 이는 [해당 명령과 동일한 방식으로 사용할 수 없음을 의미합니다. zsh그러한 문제는 없습니다(쉘 인용에는 따옴표가 사용되고 정규 표현식 연산자에서는 평소와 같이 백슬래시가 이스케이프됩니다). 따라서 연산자는 =~명령에서 작동합니다(기호의 파일 이름 확장 연산자이기 때문에 따옴표가 필요하지만).zsh[=foozsh

yash아니요, [[...]]하지만 해당 [명령에는 =~연산자(ERE 사용)가 있으며 예상대로 작동합니다(예: zsh's).

(2023년 편집) [[...]]는 2.49(2018)에서 yash에 대한 지원을 추가했으며 =~인용 측면에서 bash와 유사합니다.

어떤 경우에도 및는 [[...]]POSIX 연산자가 아니므로 =~스크립트에 사용하면 안 됩니다. sh문자열에 대한 정규식 일치를 위한 표준 명령은 다음과 같습니다 expr.

if expr "x$var" : "x$regex" > /dev/null; then...

expr정규식은 처음에 고정되어 있으므로 연산자 값 문제를 방지하려면 이 트릭 이 x필요 합니다 . 확장 정규식 대신 기본 정규식을 사용하세요.$varexprexpr

그러나 대부분의 경우 간단한 셸 패턴 일치만으로 충분하므로 정규식이 필요하지 않습니다.

case $var in
  (pattern) echo matches
esac

답변2

#!/bin/sh로 변경 #!/bin/bash하고 대신 이중 괄호를 사용하십시오.

if [[ $1 =~ $re ]]; then

이는 (일반) 테스트 명령과 반대되는 확장 테스트 명령입니다. 버전에서만 사용할 =~[[ ... ]]있으며 Bash 3.0 이상이 필요합니다.

답변3

bash이전 테스트 에서는 [정규 표현식이 지원되지 않습니다 . 대신 새 테스트를 사용해야 합니다 [[.

re="\/$"

if [[ $1 =~ $re ]]; then
        echo "${ATTENTION_PREFIX}$1 DIRECTORY MAY NOT CONTAIN A \"/\" OR LITERAL SLASH!${ATTENTION_POSTFIX}"
        exit 1
fi

더 많이 볼 수 있어요여기.

또한 #!/bin/shshebang 줄을 #!/bin/bash.

관련 정보