문자열 $string
이 glob 패턴과 일치 하는지 알고 싶습니다 $pattern
. $string
기존 파일의 이름 일 수도 있고 아닐 수도 있습니다. 어떻게해야합니까?
입력 문자열에 대해 다음 형식을 가정하십시오.
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
I는 어떨지 배시 관용구 찾고 싶은 $string
일치 할 것 $pattern1
, $pattern2
또는 다른 임의의 패턴을 글로브. 내가 지금까지 시도한 것은 다음과 같습니다.
-
[[ "$string" = $pattern ]]
이것은
$pattern
글로브 패턴이 아닌 문자열 패턴으로 해석되는 것을 제외하고 는 거의 작동합니다 . -
[ "$string" = $pattern ]
이 방법의 문제점
$pattern
은 확장 된 다음$string
의 확장과 확장 간에 문자열 비교가 수행 된다는 것 입니다$pattern
. -
[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
이것은
$string
존재 하지만 존재하는 파일이 들어있는 경우에만 작동 합니다. -
[[ $string =~ $pattern ]]
=~
연산자가$pattern
glob 또는 와일드 카드 패턴이 아닌 확장 된 정규식으로 해석 되므로 작동하지 않습니다 .
답변
이 문제에 대한 일반적인 해결책은 없습니다. 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/*
답변
zsh에서 :
[[ $string = $~pattern ]] && print true