파일 이름이 쉘 글로브 패턴과 일치하는지 프로그래밍 방식으로 알 수 있습니까? 다음과 같습니다. [[ “$string” = $pattern

문자열 $string이 glob 패턴과 일치 하는지 알고 싶습니다 $pattern. $string기존 파일의 이름 일 수도 있고 아닐 수도 있습니다. 어떻게해야합니까?

입력 문자열에 대해 다음 형식을 가정하십시오.

string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"

I는 어떨지 배시 관용구 찾고 싶은 $string일치 할 것 $pattern1, $pattern2또는 다른 임의의 패턴을 글로브. 내가 지금까지 시도한 것은 다음과 같습니다.

  1. [[ "$string" = $pattern ]]

    이것은 $pattern글로브 패턴이 아닌 문자열 패턴으로 해석되는 것을 제외하고 는 거의 작동합니다 .

  2. [ "$string" = $pattern ]

    이 방법의 문제점 $pattern은 확장 된 다음 $string의 확장과 확장 간에 문자열 비교가 수행 된다는 것 입니다 $pattern.

  3. [[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]

    이것은 $string존재 하지만 존재하는 파일이 들어있는 경우에만 작동 합니다.

  4. [[ $string =~ $pattern ]]

    =~연산자가 $patternglob 또는 와일드 카드 패턴이 아닌 확장 된 정규식으로 해석 되므로 작동하지 않습니다 .



답변

이 문제에 대한 일반적인 해결책은 없습니다. bash에서 괄호 확장 (즉, {pattern1,pattern2,...}파일 이름 확장 (일명 glob 패턴))은 별도의 것으로 간주되고 다른 조건과 시간에 따라 확장되기 때문에 bash가 수행하는 전체 확장 목록은 다음과 같습니다.

  • 버팀대 확장
  • 물결표 확장
  • 매개 변수 및 변수 확장
  • 명령 대체
  • 산술 확장
  • 단어 나누기
  • 경로명 확장

우리는 이들 중 일부에만 관심이 있기 때문에 (어쩌면 중괄호, 물결표 및 경로 이름 확장), 제어 가능한 방식으로 확장을 제한하기 위해 특정 패턴과 메커니즘을 사용할 수 있습니다. 예를 들어 :

#!/bin/bash
set -f

string=/foo/bar

for pattern in /foo/{*,foo*,bar*,**,**/*}; do
    [[ $string == $pattern ]] && echo "$pattern matches $string"
done

이 스크립트를 실행하면 다음과 같은 출력이 생성됩니다.

/foo/* matches /foo/bar
/foo/bar* matches /foo/bar
/foo/** matches /foo/bar

이것은 set -f경로 이름 확장을 비활성화하므로 명령문에서 가새 확장 및 물결 확장 만 발생 하기 때문에 작동 합니다 for pattern in /foo/{*,foo*,bar*,**,**/*}. 그런 다음 [[ $string == $pattern ]]괄호 확장이 이미 수행 된 후 테스트 작업 을 사용하여 경로 이름 확장을 테스트 할 수 있습니다 .


답변

나는이 믿지 않는 {bar,baz} 것입니다 쉘 글로브 패턴 (확실하지만 /foo/ba[rz]입니다) 당신이 알고 싶은 경우 $string일치하는 $pattern당신이 할 수 있습니다 :

case "$string" in
($pattern) put your successful execution statement here;;
(*)        this is where your failure case should be   ;;
esac

원하는만큼 할 수 있습니다 :

case "$string" in
($pattern1) do something;;
($pattern2) do differently;;
(*)         still no match;;
esac

답변

Patrick이 지적했듯이 “다른 유형”의 패턴이 필요합니다.

[[ /foo/bar == /foo/@(bar|baz) ]]


string="/foo/bar"
pattern="/foo/@(bar|baz)"
[[ $string == $pattern ]]

따옴표는 필요하지 않습니다.


답변

grep을 다음과 같이 사용합니다.

#!/bin/bash
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"

if echo $string | grep -e "$pattern1" > /dev/null; then
    echo $string matches $pattern1
fi

if echo $string | grep -e "$pattern2" > /dev/null; then
    echo $string matches $pattern2
fi

출력을 제공합니다.

./test2.bsh
/foo/bar matches /foo/*