Bash에서 문자열을 정규식과 어떻게 일치시킬 수 있습니까?


166

나는 주어진 때 있도록 기능을 포함하는 bash는 스크립트를 작성하는 것을 시도하고있다 .tar, .tar.bz2, .tar.gz등의 파일을이 파일의 압축을 관련 스위치와 타르를 사용합니다.

if elif를 사용하여 파일 이름을 테스트하여 끝나는 것을 확인하고 정규식 메타 문자를 사용하여 일치시킬 수없는 문을 사용하고 있습니다.

명령 줄에서 'test'를 사용하는 스크립트를 지속적으로 다시 작성하지 않기 위해 아래 명령문이 작동해야한다고 생각했습니다. 가능한 모든 대괄호, 따옴표 및 메타 문자 조합을 시도했지만 여전히 실패합니다.

test sed-4.2.2.tar.bz2 = tar\.bz2$; echo $?
(this returns 1, false)

나는 문제가 단순한 문제라고 확신하며 어디에서나 보았지만 어떻게 해야할지 모릅니다. 누군가 내가 어떻게 할 수 있는지 알고 있습니까?

답변:


268

정규식을 일치 시키려면 =~연산자 를 사용해야합니다 .

이 시도:

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

또는 ==연산자 와 함께 와일드 카드 (정규식 대신)를 사용할 수 있습니다 .

[[ sed-4.2.2.tar.bz2 == *tar.bz2 ]] && echo matched

이식성이 문제가되지 않는다면, [[대신에 [또는 test더 안전하고 강력하게 사용 하는 것이 좋습니다 . 테스트와 [와 [[의 차이점무엇입니까? 자세한 내용은.


7
두 번째 예에서 glob 와일드 카드 일치에주의하십시오. [[]] 내에서 *는 패턴과 일치하는 현재 디렉토리의 파일 이름과 일치하도록 보통 그대로 확장되지 않습니다. 어떤 맥락. [[]] 안에서만 작동합니다. 그렇지 않으면 기존 파일 이름으로 확장됩니다.
Alan Porter

7
정규식에 따옴표를 사용하려고했지만 실패했습니다. 이 답변 은이 작업을 수행하는 데 도움 되었습니다 check="^a.*c$";if [[ "abc" =~ $check ]];then echo match;fi. 정규 표현식을 var에 저장해야합니다.
Aquarius Power

또한 정규 표현식 (perl과 같이)은 괄호 안에 있으면 [[ sed-4.2.2.tar.bz2 == "*tar.bz2" ]]안됩니다. 작동하지 않습니다.
pevik

18
FWIW에서 부정에 대한 구문 (즉, 일치하지 않음 )은 [[ ! foo =~ bar ]]입니다.
Skippy le Grand Gourou

1
대시는 -n 1매개 변수를 지원하지 않으며 변수에 자동으로 넣지도 않습니다 $REPLY. 조심해!

54

이것을하는 기능

extract () {
  if [ -f $1 ] ; then
      case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       rar x $1       ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)           echo "don't know '$1'..." ;;
      esac
  else
      echo "'$1' is not a valid file!"
  fi
}

다른 주

위의 의견에서 Aquarius Power에 대한 답변으로, We need to store the regex on a var

변수 BASH_REMATCH는 표현과 일치하고, $ {BASH_REMATCH [n이]} 다음에 괄호 예에 싸여 n 번째 그룹을 일치합니다 후 설정 ${BASH_REMATCH[1]} = "compressed"${BASH_REMATCH[2]} = ".gz"

if [[ "compressed.gz" =~ ^(.*)(\.[a-z]{1,5})$ ]]; 
then 
  echo ${BASH_REMATCH[2]} ; 
else 
  echo "Not proper format"; 
fi

(위의 정규식은 파일 이름 지정 및 확장명에 유효한 것이 아니지만 예제에서 작동합니다.)


또한 BSD tar를 사용하면 모든 형식에 대해 "tar xf"를 사용할 수 있으며 별도의 명령이나이 기능이 필요하지 않습니다.
좋은 사람

aGNU tar 또는 pBSD tar에서 확장자에서 압축 유형을 자동으로 추론하도록 명시 적으로 지시합니다. GNU tar는 그렇지 않으면 자동으로 수행하지 않으며 @GoodPerson의 의견에서 BSD tar가 기본적으로 수행한다고 추측합니다.
Mark K Cowan

7z 포장 풀기 .. AR, ARJ, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, RPM, SquashFS , UDF, UEFI, VDI, VHD, VMDK, WIM, XAR 및 Z. 7-zip.org
mosh

14

여기에 의견을 말할 충분한 담당자가 없으므로 dogbane의 답변을 개선하기 위해 새로운 답변을 제출하고 있습니다. 점. 정규 표현식에서

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

'tar.bz2'사이의 리터럴 점뿐만 아니라 모든 문자와 실제로 일치합니다.

[[ sed-4.2.2.tar4bz2 =~ tar.bz2$ ]] && echo matched
[[ sed-4.2.2.tar§bz2 =~ tar.bz2$ ]] && echo matched

또는 '\'로 이스케이프 할 필요가없는 것 그러면 엄격한 구문은

[[ sed-4.2.2.tar.bz2 =~ tar\.bz2$ ]] && echo matched

또는 더 엄격하게 갈 수 있고 정규식에 이전 점을 포함시킬 수도 있습니다.

[[ sed-4.2.2.tar.bz2 =~ \.tar\.bz2$ ]] && echo matched

9

bash를 사용하고 있으므로이를 위해 자식 프로세스를 만들 필요가 없습니다. bash 내에서 완전히 수행하는 솔루션은 다음과 같습니다.

[[ $TEST =~ ^(.*):\ +(.*)$ ]] && TEST=${BASH_REMATCH[1]}:${BASH_REMATCH[2]}

설명 : 시퀀스 "콜론 및 하나 이상의 공백"전후의 그룹은 BASH_REMATCH 배열의 패턴 일치 연산자에 의해 저장됩니다.


1
인덱스 0은 전체 일치를 포함하고 인덱스 1과 2는 그룹 일치를 포함합니다.
Rainer Schwarze

3
if [[ $STR == *pattern* ]]
then
    echo "It is the string!"
else
    echo "It's not him!"
fi

나를 위해 작동합니다! GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)


1
이것은 매우 위험합니다. 현재 디렉토리에 리터럴 서브 스트링 "pattern"이라는 파일이 없기 때문에 정의되지 않은 작동없이 작동합니다. 계속해서 그런 이름의 파일을 만들면 하위 문자열 확장이 파일과 일치하고 여러 가지 빛깔의 heisenbugs로 모든 것을 무너 뜨릴 것입니다.
i336_

그러나 현재 디렉토리에 `1pattern, pattern pattern2 및 pattern 파일이있는 실험 을했습니다. 이 스크립트는 예상대로 작동합니다. 테스트 결과를 알려주시겠습니까? @ i336_
juan cortez

2
@ i336 : 그렇게 생각하지 않습니다. 내 [[ ... ]]에서 rhs glob 패턴 은 일반적으로 그러 하듯이 현재 디렉토리에 따라 확장 되지 않습니다 .
user1934428

@ i336_ 아니요 [[...]]. Bash는 파일 이름 확장을 수행하지 않습니다. bash 매뉴얼에서Word splitting and filename expansion are not performed on the words between the [[ and ]];
jinbeom hong

@jinbeomhong : 틸. 알아두면 좋습니다, 감사합니다!
i336_

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.