쉘 스크립트에서 대소 문자를 구분하지 않는 문자열 비교


129

==연산자는 쉘 스크립트에서 두 문자열을 비교하는 데 사용됩니다. 그러나 대소 문자를 무시하고 두 문자열을 비교하고 싶습니다. 어떻게 수행 할 수 있습니까? 이에 대한 표준 명령이 있습니까?

답변:


72

배쉬가 있다면

str1="MATCH"
str2="match"
shopt -s nocasematch
case "$str1" in
 $str2 ) echo "match";;
 *) echo "no match";;
esac

그렇지 않으면 사용중인 쉘을 알려주십시오.

대안, awk 사용

str1="MATCH"
str2="match"
awk -vs1="$str1" -vs2="$str2" 'BEGIN {
  if ( tolower(s1) == tolower(s2) ){
    print "match"
  }
}'

32
if문을 사용하여 문자열을 비교하는 사람 은 단일 브래킷 형식 대신 shopt이중 브래킷 [[ ]]형식의 조건부 를 사용해야합니다 [ ]. 참조 : gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html을
개별 선택

3
질문은 ==두 문자열을 비교하는 데 사용되지만 응답은 case명령문을 사용하여 대소 문자를 구분하지 않는 비교를 보여줍니다 . 안심의 shopt솔루션은 또한의 대소 문자를 구분 사용 가능 ==, =~및 기타 문자열 비교 연산자를.
taranaki

7
아마도 shopt -u nocasematchbash의 기본값으로 되돌리려면 비교가 끝난 후에 실행하는 것이 현명합니다 .
하드 슈나이더

6
nocasematch설정 을 저장하고 복원하는 것이 가장 좋습니다. 그것을 가지고 와서 그것을 SHELLNOCASEMATCH=`shopt -p nocasematch`변경하고 shopt -s nocasematch완료되면 그것을 복원하십시오$SHELLNOCASEMATCH
Urhixidur

2
더 나은 여전히 : SHELLNOCASEMATCH=$(shopt -p nocasematch; true)때문에, shopt -p코드 1과 함께 종료됩니다 옵션이 설정되지 않으며,이 경우 취소 할 수있는 스크립트를 일으킬 수있는 경우에 set -e유효입니다.
우리는 모두 모니카

158

Bash에서는 매개 변수 확장을 사용하여 문자열을 모두 소문자 / 대문자로 수정할 수 있습니다.

var1=TesT
var2=tEst

echo ${var1,,} ${var2,,}
echo ${var1^^} ${var2^^}

14
shopt 옵션을 암시하지 않는 회신입니다. 따라서 두 문자열 무시 대소 문자를 비교할 수 있으며 동일한 테스트에서 다른 두 문자를 대소 문자와 비교할 수 있습니다. 감사합니다
jehon

37
이것은 Bash 4의 새로운 기능입니까? 적어도 Bash 3.2.51 (OS X 10.9에서 사용)에서는 작동하지 않습니다. 첫 번째 echo결과는 다음과 같습니다.-bash: ${var1,,}: bad substitution
Felix Rabe

1
이러한 대소 문자를 구분하지 않는 비교 구현은 현지화 문제 (예 : 터키어 I 문제)가 발생하기 쉽습니다. shopt -s nocasematch구현 방법을 모르지만 일반적으로 이러한 "언어 수준"솔루션이 올바르게 처리합니다.
하드 슈나이더

5
@Ohad 슈나이더, 터키어 현지화 문제에 대한 터키의 걱정을하자, 난 그냥 문자열 일치에 대한 신속하고 효율적인 방법이 필요하고이 huuuuuge의 차이로 케이크 소요
niken

1
macOS 사용자의 경우 Bash 버전을 업그레이드하십시오. 이 시점에서 귀하는 10 년이 넘었습니다. itnext.io/upgrading-bash-on-macos-7138bd1066ba
Jason Carter

114

이 모든 대답은 Bash 4가있는 한 가장 쉽고 빠른 방법을 무시합니다.

if [ "${var1,,}" = "${var2,,}" ]; then
  echo ":)"
fi

당신이하고있는 일은 두 문자열을 모두 소문자로 변환하고 결과를 비교하는 것입니다.


6
이것은 Bash 4 이상에서만 사용할 수 있습니다 (예 : Mac OS X 10.11에서는 해당되지 않음)
d4Rk

8
@ d4Rk이므로 내 대답의 첫 번째 문장에 "Bash 4가있는 한"이 표시됩니다. 그러나 Bash 4는이 의견을 쓸 때 7 년 이상 동안 사용되어 왔으며 OS X 설치는 거의 오랫동안 그렇게했습니다.
Riot

@Riot 죄송합니다, 처음에 그것을 알아 차리지 못했습니다. OS X에 원하는 모든 bash를 설치할 수 있지만 기본값은 3.2이며 내 스크립트는 다른 Mac에서도 실행되어야하므로 실제로는 옵션이 아닙니다.
d4Rk

2
이해할 수있는 @ d4Rk-이식성을 실제로 보장 해야하는 경우 POSIX 셸 표준을 고수하는 것이 좋습니다. 경우에 따라 bash 버전을 찾지 못할 수도 있습니다.
Riot

1
이것이 바로 내가 찾던 것입니다. =)
Robin Winslow

39

nocasematch 상태를 저장하십시오 (다른 기능이 사용 불가능한 경우에 따라 다름).

local orig_nocasematch=$(shopt -p nocasematch)
shopt -s nocasematch
[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"
$orig_nocasematch

참고 : local함수 안에있는 경우 에만 사용 하십시오.


4
니스 때문에 case(ghostdog의 대답에 포함) 문은 항상 내 피부 크롤 할 것
SeldomNeedy

15

한 가지 방법은 두 문자열을 모두 위 또는 아래로 변환하는 것입니다.

test $(echo "string" | /bin/tr '[:upper:]' '[:lower:]') = $(echo "String" | /bin/tr '[:upper:]' '[:lower:]') && echo same || echo different

다른 방법은 grep을 사용하는 것입니다.

echo "string" | grep -qi '^String$' && echo same || echo different

tr알파인 (를 sh통해 제공 되는 busybox) 기반의 도커 크기의 응용 프로그램에서 방법을 사용했습니다 . 감사합니다.
MXWest

7

korn 쉘의 경우 typeset 내장 명령을 사용합니다 (소문자는 -l, 대문자는 -u).

var=True
typeset -l var
if [[ $var == "true" ]]; then
    print "match"
fi

2
이것은 awk 또는 다른 프로세스를 시작하는 것보다 성능면에서 더 좋습니다.
Alex

1
bash에서, 선언 -l 또는 -u를 사용하여 속성을 설정할 수 있습니다.
Bharat

5

대소 문자를 구분하지 않는 라인 비교를 fgrep하면 매우 쉽습니다.

str1="MATCH"
str2="match"

if [[ $(fgrep -ix $str1 <<< $str2) ]]; then
    echo "case-insensitive match";
fi

if fgrep -qix -- "$str1" <<<"$str2"; then대신 사용하는 것이 좋습니다.

3

다음은 tr을 사용하는 솔루션입니다.

var1=match
var2=MATCH
var1=`echo $var1 | tr '[A-Z]' '[a-z]'`
var2=`echo $var2 | tr '[A-Z]' '[a-z]'`
if [ "$var1" = "$var2" ] ; then
  echo "MATCH"
fi

3

grep-i대소 문자를 구분을 의미하므로 VAR2가 var1에있는 경우 당신에게 그것을 요구 플래그.

var1=match 
var2=MATCH 
if echo $var1 | grep -i "^${var2}$" > /dev/null ; then
    echo "MATCH"
fi

3
var2에 정규식 특수 문자가 있으면 작동하지 않습니다.
haridsv 2013

3

들어 zsh구문 약간 다른,하지만 여기에 대부분의 응답에 비해 여전히 짧은 :

> str1='mAtCh'
> str2='MaTcH'
> [[ "$str1:u" = "$str2:u" ]] && echo 'Strings Match!'
Strings Match!
>

비교하기 전에 두 문자열을 모두 대문자로 변환합니다.


또 다른 방법은 zsh 's globbing flags를 사용하므로 iglob 플래그 를 사용하여 대소 문자를 구분하지 않는 일치를 직접 사용할 수 있습니다 .

setopt extendedglob
[[ $str1 = (#i)$str2 ]] && echo "Match success"
[[ $str1 = (#i)match ]] && echo "Match success"


1

대소 문자를 구분하는 패턴 에 대해이 훌륭한 블로그 / 튜토리얼 / 무엇이든 보았습니다 . 다음 세 가지 방법이 예제와 함께 자세히 설명됩니다.

1. tr 명령을 사용하여 패턴을 소문자로 변환

opt=$( tr '[:upper:]' '[:lower:]' <<<"$1" )
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other options"
                ;;
esac

2. 대소 문자 패턴이있는 정규식 사용

opt=$1
case $opt in
        [Ss][Qq][Ll])
                echo "Running mysql backup using mysqldump tool..."
                ;;
        [Ss][Yy][Nn][Cc])
                echo "Running backup using rsync tool..."
                ;;
        [Tt][Aa][Rr])
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

3. nocasematch를 켭니다

opt=$1
shopt -s nocasematch
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

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