シェルスクリプト内の文字列の大文字と小文字を区別しない比較


129

==オペレータは、シェルスクリプト内の2つの文字列を比較するために使用されます。ただし、大文字と小文字を区別せずに2つの文字列を比較したいのですが、どうすればよいですか?これのための標準的なコマンドはありますか?

回答:


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
indiv

3
質問は==2つの文字列を比較するために使用されることを示していますが、応答はcaseステートメントを使用した大文字と小文字を区別しない比較を示しています。安心させる、shopt溶液はまた、大文字と小文字を区別しない使用を可能===~および他の文字列比較演算子。
taranaki 2015

7
おそらくshopt -u nocasematch、bashのデフォルトに戻すために、比較が行われた後に実行するのが賢明です。
Ohad Schneider 2017

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オプションを意味しない返信。したがって、大文字と小文字を無視して2つの文字列を比較し、同じテストで、他の2つの文字列を大文字と比較することができます。ありがとう
jehon

37
これはBash 4の新機能ですか?バッシュ3.2.51で少なくともそれが動作しない(OS X 10.9で使用) -最初のecho文の結果をに:-bash: ${var1,,}: bad substitution
フェリックスラーベ

1
このような大文字と小文字を区別しない比較の実装では、ローカライズの問題(トルコ語Iの問題など)が発生しやすくなります。shopt -s nocasematch実装方法はわかりませんが、通常、このような「言語レベル」のソリューションでは正しく処理されます。
Ohad Schneider

5
@Ohad Schneider、トルコ語のローカリゼーションの問題をトルコ人に心配させてください。文字列の照合をすばやく効率的に行う方法が必要です。これにより、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は
除く

8
@ d4Rkが私の回答の最初の文に「Bash 4がある限り」と書かれている理由です。とは言っても、このコメントを書いている時点でBash 4は7年以上前にリリースされており、私自身のOS Xインストールではほぼ同じくらい長い間それがありました。
Riot 2016年

@Riot申し訳ありませんが、そもそもそれに気づきませんでした。私はあなたがOS Xに好きなbashをインストールできることを知っていますが、デフォルトは3.2であり、私のスクリプトは別のMacでも実行する必要があるため、これは本当に私にとってオプションではありません。
d4Rk 2016年

2
理解できる@ d4Rk-移植性を本当に保証する必要がある場合は、POSIXシェル標準を使用することをお勧めします。
暴動

1
これはまさに私が探していたものです。より高いはずです=)
ロビンウィンスロー

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

1つの方法は、両方の文字列を上位または下位に変換することです。

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では、declare -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を使用しますglobbing flags。これにより、iglobフラグを使用して、大文字と小文字を区別しないマッチングを直接利用できます。

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


1

大文字と小文字を区別するパターンの扱いについて、この素晴らしいブログ/チュートリアル/何にでも遭遇しました。次の3つの方法について、例を使用して詳細に説明します。

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.