文字セットとエンコーディングの簡単な紹介
ドキュメントが画面に表示されると、人間はドキュメントを一連の文字として解析します (コンピューターのテキスト処理では、グリフとも呼ばれます)。ただし、ドキュメントがディスクに保存されている場合、他のすべての種類のファイルと同様に、ドキュメントは一連のバイトとして書き込まれます。したがって、文字からバイトへの変換、およびその逆の変換を処理するシステムを配置する必要があります。
このような方式を文字エンコーディングと呼びます。エンコーディングはコンピューターで実装する必要があるため、適切に定義する必要があります。そのため、各エンコーディングは定義済みの文字セットのみを処理できます。これは当然のことながら文字セットと呼ばれます。
一部のエンコーディングは、常に各文字を 1 バイトで表します。これらはシングルバイトエンコーディングと呼ばれます。他のエンコーディングは各文字に複数のバイトを使用し、すべての可能な文字に対して必ずしも同じ数ではありません。これらはマルチバイト エンコーディングと呼ばれます。
要約すると、テキスト ドキュメントには、あらかじめ定義された文字セットから抽出された文字が論理的に含まれていますが、コンピューターはバイト単位で機能するため、文字をバイトに、またはその逆に変換する文字エンコーディングを作成します。一部のエンコーディングは、1 つの文字を表すために複数のバイトを使用するため、マルチバイトと呼ばれます。
あなたの問題に戻る
テキスト ファイルをディスクに保存したとき、メモ帳は何らかのエンコーディングを使用してそれを実行しました (マルチバイト エンコーディングでしたが、今のところそれがわからないことにしましょう)。テキスト内の文字¬
には、バイト形式で特定の表現が与えられました。
PHP ファイルをディスクに保存したとき、ソース コード エディタは何らかのエンコーディングを使用してそれを行いました。文字¬
列リテラル '/¬/' の文字には、バイト形式で特定の表現が与えられました。
デフォルトpreg_replace
では、PHP のすべての汎用文字列関数と同様に、バイナリ モードで動作します。これは、バイト単位で機能することを意味します。これは、エンコーディングを認識し、ソースを文字単位で表示するソース コード エディターとは対照的です。その結果、文字¬
( NOT SIGN ) であると思われるものを置き換えるとpreg_replace
、実際には一連のバイトが置き換えられます。正確な形式は、PHP ソースのエンコーディングによって異なります。
そこに問題があります。テキスト ファイルとソースのエンコーディングが一致しない場合、テキストに実際に何が起こるかについて、すべての賭けが外れます。
あなたが示した結果を考えると、あなたのケースで起こったことはおそらくこれです:
- テキスト ファイルは、マルチバイト エンコーディングで保存されています。
- PHP ソースはシングルバイトエンコーディングで保存されました。
¬
PHP ソース内ののシングルバイト表現は¬
、テキスト内の のマルチバイト表現の一部であったため、これらのバイトの1 つが消去されました。
- 残りのバイトはエンコーディングの規則に適合しないため、置換後のテキストを表示するプログラムは、「ここに何かがありますが、認識できる文字ではありません」という疑問符を表示します。
修正方法
上記に沿ったいくつかの可能性がありますが、それらはすべて 1 つの共通の属性を共有しています:テキスト ファイルのエンコーディングを知っている必要があります(これはメモ帳で簡単に行うことができます: [名前を付けて保存] をクリックし、ダイアログ ボックスの下部を確認します。 )。次に、次のことができます。
- 同じエンコーディングを使用してテキスト ファイルと PHP ソースを保存すると、すべてが機能します。これはこれまでで最も簡単です。
テキスト ファイルのエンコーディングでターゲット文字を表すバイトを PHP ソースに挿入します。たとえば、テキスト ファイルが UTF-8 として保存されているとします。このエンコーディングは問題の文字をバイト シーケンス 0xC2 0xA2 で表すため、次のようにコードを記述してこのバイト シーケンスを置き換えることができます。
preg_replace("/\xc2\xa2/", '', $string)
テキスト ファイルのエンコーディングが UTF-8 のままである限り、PHP ソースのエンコーディングに関係なく機能します。