파일 이름이 쉘 글로브 패턴과 일치하는지 프로그래밍 방식으로 알 수 있습니까?


13

문자열 $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 또는 와일드 카드 패턴이 아닌 확장 된 정규식으로 해석 되므로 작동하지 않습니다 .


2
당신이 겪을 문제 {bar,baz}는 패턴이 아니라는 것입니다. 매개 변수 확장입니다. 점에서 미묘하지만 중요한 차이는 {bar,baz}여러 인수에 매우 초기에 확대되어 barbaz.
Patrick

쉘이 매개 변수를 확장 할 수 있다면 문자열이 글로브의 잠재적 확장인지 알 수 있습니다.
jayhendren

이 A A =을 시도해 ls /foo/* 당신이에 일치시킬 수 해주기
Hackaholic

1
@ 패트릭 : bash 맨 페이지를 읽은 후에 foo/{bar,baz}실제로 foo/*경로 이름 확장 인 동안 실제로 매개 변수 확장이 아닌 중괄호 확장 이라는 것을 알았습니다 . $string매개 변수 확장입니다. 이들은 모두 다른 시간과 다른 메커니즘으로 수행됩니다.
jayhendren

@jayhendren @Patrick은 옳습니다. 그리고 당신은 당신의 질문이 궁극적으로 제목이 믿게하는 것이 아니라는 것을 알게되었습니다. 오히려 다양한 패턴과 문자열을 일치 시키려고합니다. glob 패턴과 엄격하게 일치 시키려면 case명령문은 Bash 매뉴얼에 따라 경로 이름 확장 ( "globbing")을 수행합니다.
Mike S

답변:


8

이 문제에 대한 일반적인 해결책은 없습니다. 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 ]]괄호 확장이 이미 수행 된 후 테스트 작업 을 사용하여 경로 이름 확장을 테스트 할 수 있습니다 .


7

나는이 믿지 않는 {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

1
안녕 @ mikeserv, 의견과 위에서 제공 한 답변에서 알 수 있듯이, 나는 당신이 말하는 것이 사실이라는 것을 이미 배웠습니다 {bar,baz}. 나는 이미 이것을 고려한 내 질문에 대한 해결책을 생각해 냈습니다.
jayhendren

3
+1 제목과 첫 문장에 주어진대로 정확하게 대답합니다. 이 질문은 나중에 셸 글로 패턴으로 다른 패턴을 강조합니다.
Mike S

3

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

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


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

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


좋아, 이것은 작동하지만 엄밀히 말하면 내 질문에 대답하지 않습니다. 예를 들어, 다른 소스에서 나오는 패턴, 즉 패턴이 제어 할 수없는 패턴을 고려하고 싶습니다.
jayhendren

@jayhendren 그렇다면 아마도 들어오는 패턴을 bash가 받아들이는 것으로 변환해야 할 것입니다.
Hauke ​​Laging

그래서 당신이 실제로 한 일은 내 질문을 "파일 이름이 식의 잠재적 확장인지 어떻게 알 수 있습니까?"에서 "일반 bash 스타일 파일 이름 패턴을 bash 스타일 확장 글로 패턴으로 변환하는 방법"으로 변환되었습니다.
jayhendren

@jayhendren 당신이 원하는 것이 불가능하다고 보인다는 것을 고려하면 "정말 다 끝났어요"는 조금 이상하게 들리 겠지만 아마도 외국어 일 수도 있습니다. 이 새로운 질문을하려면 입력 패턴이 어떻게 보이는지 설명해야합니다. 아마도 간단한 sed작업 일 것입니다.
Hauke ​​Laging

1
@HaukeLaging이 정확합니다. 글로브 패턴 (일명 "경로명 확장")과 일치하는 방법을 찾기 위해 여기에 오는 사람들은 제목이 "쉘 글로브 패턴"이라고 말하지만 그의 질문의 내용은 글로브 패턴을 사용하지 않기 때문에 혼란 스러울 수 있습니다. . 어느 시점에서 jayhendren은 그 차이점에 대해 배웠지 만 그의 초기 혼란은 Hauke가 자신의 방식에 응답하게 한 원인입니다.
Mike S

1

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/*

-2

zsh에서 :

[[ $string = $~pattern ]] && print true

1
이 질문에는 bash 쉘이 사용될 것이라고 명시되어 있습니다.
jayhendren
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.