コマンド出力の大文字と小文字を区別しない部分文字列の一致を行うシェルスクリプトを作成するにはどうすればよいですか?
最初に、大文字と小文字を区別しない簡単なスクリプト例を示します。
#!/bin/bash
if [ $(echo hello) == hello ]; then
echo it works
fi
右側の文字列helloを変更すると、it works
がエコーされなくなります。 echo hello
を任意のコマンドに置き換えてみてください。大文字と小文字を無視したい場合で、どちらの文字列にも改行が含まれていない場合は、grepを使用できます。
#!/bin/bash
if echo Hello | grep -iqF hello; then
echo it works
fi
ここで重要なのは、コマンド出力をgrep
にパイプ処理していることです。 if
ステートメントは、パイプラインの右端のコマンド(この場合はgrep)の終了ステータスをテストします。一致が見つかった場合にのみ、grepは成功して終了します。
Grepの-i
オプションは、大文字と小文字を区別しないと言っています。-q
オプションは、最初の一致後に出力を発行せずに終了することを示しています。-F
オプションは、引数を正規表現ではなく文字列として扱うことを示しています。
最初の例では[ expression ]
を使用しているため、直接比較やさまざまな便利な演算子を使用できます。 2番目の形式は、コマンドを実行し、その終了ステータスをテストするだけです。
bash
シェルオプションを設定すると、正規表現演算子=~
を使用して、nocasematch
で大文字と小文字を区別しない部分文字列マッチングをネイティブに実行できます。例えば
s1="hElLo WoRlD"
s2="LO"
shopt -s nocasematch
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
match
s1="gOoDbYe WoRlD"
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
no match
変数needle
の値で変数haystack
の値の大文字と小文字を区別する文字列検索の場合:
case "$haystack" in
*"$needle"*) echo "present";
*) echo "absent";
esac
大文字と小文字を区別しない文字列検索の場合、両方を同じ大文字と小文字に変換します。
uc_needle=$(printf %s "$needle" | tr '[:lower:]' '[:upper:]' ; echo .); uc_needle=${uc_needle%.}
uc_haystack=$(printf %s "$haystack" | tr '[:lower:]' '[:upper:]' ; echo .); uc_haystack=${uc_haystack%.}
case "$uc_haystack" in
*"$uc_needle"*) echo "present";;
*) echo "absent";;
esac
GNU coreutilsのtr
はマルチバイトロケール(UTF-8など)をサポートしていません。マルチバイトロケールを使用するには、代わりにawkを使用してください。 awkを使用するには、変換だけでなく文字列比較を行うようにすることができます。
if awk 'BEGIN {exit !index(toupper(ARGV[2]), toupper(ARGV[1]))}' "$needle" "$haystack"; then
echo "present"
else
echo "absent"
fi
BusyBoxのtr
は[:CLASS:]
構文をサポートしていません。代わりにtr a-z A-Z
を使用できます。 BusyBoxは非ASCIIロケールをサポートしていません。
Bash(shではない)バージョン4.0以降では、大文字と小文字を変換するための組み込みの構文と、文字列照合のためのより単純な構文があります。
if [[ "${haystack^^}" = *"${needle^^}"* ]]; then
echo "present"
else
echo "absent"
esac