
私はLinuxでbashを使用しています。次のifステートメントで成功しましたが、失敗コードを返すべきではありませんか?
if [[ ■ = [⅕⅖⅗] ]] ; then echo yes ; fi
四角形はどんな文字と同じではなく、なぜ成功コードが出てくるのか理解できません。
私のボックスに二重括弧を保管することが重要です。
この場合、範囲を達成する他の方法や他の提案はありますか?
答え1
これは、これらの文字が同じソート順序を持っているためです。
あなたも気づきます。
sort -u << EOF
■
⅕
⅖
⅗
EOF
1行だけが返されます。
または:
expr ■ = ⅕
trueを返します(POSIXが要求するように)。
GNUシステムに付属のほとんどのロケールには、同じソート順を持つ多くの文字(または文字シーケンス(組み合わせシーケンス))があります。 ■⅕⅖⅗の場合、順序が定義されておらず、順序が定義されていない文字は最終的にGNUシステムで同じソート順序を持つためです。 şやŞなどの一部の文字は、同じ並べ替え順序を持つように明示的に定義されています(もちろん、これがどのように実行されるかについての明確な実際の論理や一貫性はありませんが)。
これは驚くべき誤った行動の源です。私は持っていますこの質問は最近オースティンのパネルで提起されました。(POSIXおよび単一のUNIX仕様の後ろにある本文)メーリングリスト、2015年4月3日現在、議論は進行中です。
この場合、位置と順序を同じに[y]
一致させる必要があるかどうかはわかりませんが、角かっこ式は組み合わされた要素と一致するように意図されているため、これは期待される動作であることを示しています。x
x
y
bash
とにかく、私は[⅕-⅕]
少なくとも[⅕-⅖]
一致する必要があると思います■
。
さまざまなツールが異なる動作をしていることがわかります。 ksh93はbash
GNUのように動作するかどうかgrep
ですsed
。他のいくつかのシェルは異なる動作をし、いくつかははるかにyash
バグがたくさんあります。
一貫した動作を得るには、すべての文字が異なる順序で配置されるロケールが必要です。 C ロケールは一般的なロケールです。しかし、ほとんどのシステムでは、Cロケールの文字セットはASCIIです。 GNUシステムでは、通常、C.UTF-8
UTF-8文字を処理するために使用できるロケールにアクセスできます。
だから:
(export LC_ALL=C.UTF-8; [[ ■ = [⅕⅖⅗] ]])
またはそれに対応する標準:
(export LC_ALL=C.UTF-8
case ■ in ([⅕⅖⅗]) true;; (*) false; esac)
falseを返す必要があります。
別の選択肢はCに設定することですLC_COLLATE
。これはGNUシステムでは機能できますが、マルチバイト文字のソート順を指定できないため、他のシステムでは必ずしも機能する必要はありません。
教訓の一つは平等文字列を比較すると、概念は思ったほど明確ではありません。平等は、最も厳しいものから最も厳しくないものまでを意味します。
- バイト数は同じで、すべてのバイトコンポーネントは同じ値を持ちます。
- 文字数が同じで、すべての文字が同じです(たとえば、現在の文字セットの同じコードポイントを参照)。
- ロケールのソートアルゴリズムによると、2つの文字列のソート順序は同じです(つまり、a <bまたはb> aは真ではありません)。
今、2または3の場合、両方の文字列に有効な文字が含まれているとします。 UTF-8および他のいくつかのエンコーディングでは、特定のバイトシーケンスは有効な文字を形成しません。
したがって、一部の文字には2つ以上の可能なエンコードがある可能性があるため、1と2は必ずしも同じではありません。これは通常、ISO-2022-JPなどのステートフルエンコードの場合です。A
これは、41
または1b 28 42 41
(1b 28 42
ASCIIに切り替えるシーケンスです。好きなだけエンコードを挿入できるので違いはありません。))エンコーディングとうまく機能しません。
また、GNU以外のほとんどのユーティリティはゼロバイト値(ASCIIのNUL文字)を処理できないことに注意してください。
そのどれ定義使用方法は、ユーティリティとユーティリティの実装またはバージョンによって異なります。 POSIXはこれについて100%明確ではありません。 C言語環境では、3つとも同じです。 YMMV外部。
答え2
あなたは間違っています。=
そして==
それは違います。
次の例を試してください。
if [[ "■" == "[⅕⅖⅗]" ]] ; then echo yes ; else echo no ; fi
if [[ "1" == "1" ]] ; then echo yes ; else echo no ; fi
if [[ "■" == "■" ]] ; then echo yes ; else echo no ; fi