• ベストアンサー

正規表現 文中空白可能

ereg関数を使用してフォームの「ふりがな」のチェックをしていますが、ふりがなの文中に空白が含まれていてもチェックにひっかからないようにする(下記コードで「ふりがなOK」と表示する)には、どのようにすればよいのでしょうか? 私が、現在、トライしているコードです。 if (!ereg("^([あ-ん])+([あ-んー\s])*$", $applicant_kana)) { echo 'ふりがなエラー'; } else { echo 'ふりがなOK'; } 上記のコードで、「これは ふりがなです」と入力した場合に「ふりがなOK」と表示させたいのです。文中に空白が存在しても「ふりがなOK」と表示されるように\sを使用しましたが、現在のコードでは文中に空白があると「ふりがなエラー」と表示されてしまいます。 mb_eregではなく、eregを使用していますが、私の環境ではプログラムの動作に問題は起きていません。mb_eregでも検証しましたが、動作に違いはありませんでした。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

ソースも参照して調べてみましたが、どうも ereg は本当に古い時代の仕様を踏襲しているようです。 <?php $regs = ""; ereg("[\\x]+", "--\\x\\---", $regs); echo $regs[0]; これを実行すると、 \x\ という出力が得られます。 つまり、ブラケットの中のエスケープは常に無効です。 したがって、'-' をエスケープする形で使うことはeregではできません。 たとえば [\-@] のようにすると、'\' から '@' の間の範囲指定と解釈してしまい、これは 文字コードとしては順序が逆転しているので警告がでます。

kitty1000
質問者

補足

sakusaker7さん ご回答ありがとうございました。 一通り分からなかったことをご回答いただいたので、一旦スレッドを締め切ります。

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

> if (!ereg("^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \-]*$", $roman)) { > この正規表現でちゃんと動作しているのですが「\-」を[]の最後に位置させないと(]の直前)、 > いくら「\」で「-」をエスケープしていても、エラーになるのです。 それは、ereg関数に渡される前に "^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \-]*$" がPHPにより走査されていて そのときにエスケープキャラクタの処理が行われてしまうからです。 その結果として "^[a-zA-Z0-9]+[a-zA-Z0-9.-&, -]*$" のように、'\' が抜けた文字列が eregに渡されることになるのでエラーになるのです。 そして、'-' を最後に置くとエラーにならないのは「歴史的な理由(historicaly reason」により ってやつです。 もともと、文字クラスの中では '\' によるエスケープも利かないという処理系がほとんどでした。 この場合、'['や']'、'-' をどのように表現するかという問題が生じますが、 特別に以下のようなルールが適用されます。 ・[ の直後の ] は文字クラスを閉じるメタ文字ではなく、']'そのものとする。 #[^ のときはその直後 ・[ から ] の間にある '[' はキャラクタそのものとする ・- は ]の直前に置かれた場合には範囲指定の間に置かれる文字ではなく '-' そのもとする ということなので、末尾に置いたときはエラーにならない。 というわけです。 まあこんな昔の仕様を覚えていてもあんまり役には立ちませんけどね。 この仕様に従ってないものも最近ではありますし。

kitty1000
質問者

補足

sakusaker7さん ご回答、ありがとうございました。 上記のsakusaker7さんの回答からすると、下記のコードでも間違いではないと言うことでしょうか? > if (!ereg("^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \-]*$", $roman)) { ちなみに- を ]の直前に置かずにエスケープするには、どうすればよいですか?\-では、\- を ]の直前に置かない限りエラーになってしまいます。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

>ereg内での「\t」が半角空白で、mb_ereg又はpreg内では「\t」が半角空白及び「\s」が全角空白の正規表現ということになるのですかね? \t はタブを表すだけです(三種類のどれでも)。 > [a-zA-Z0-9.-&, \t]*$ わかりづらいかもしれませんが、, のうしろ、\tの前に空白が一個置いてあります。 Perlだと設定をきちんとすれば \s で全角空白も 引っかかるんですが、PHPはどうだったかなあ。引っかからないような気がしたんですが。 ですので、mb_ereg/preg の場合でしたら [] の中に、全角空白 ' ' そのものを含めてください。 > 正規表現の判定にpregを使用する場合でも、判定内容が漢字などの2バイト文字の場合、 > mb_regex_encodingで正規表現用文字コードを予め宣言しておく必要があるのでしょうか? 必要ありません(というかpreg_*と mb_regex_encodingは無関係です)。 ただし、preg_* はsjisやeuc-jpには対応していなくて 使えるのはUTF-8だけです。 ですので、preg_*にわたす引数はUTF-8に変換してください。そして マッチ時のフラグとして、/U を忘れずにつけてください。 preg_match("/[…][…]+/U", … こんな感じ。

kitty1000
質問者

お礼

上記の「回答への補足」のローマ字の表現のチェックに誤りがありましたので、修正します。 修正前: >if (!ereg("^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \-]*$", $roman)) { 修正後: if (!ereg("^[a-zA-Z0-9]+[a-zA-Z0-9.&, \-]*$", $roman)) {

kitty1000
質問者

補足

sakusaker7さん ご回答ありがとうございました。 現在検証中ですが、やりたいことはできるようになったと思います。 以下の件が気になりましたので、お聞きしたいのですが: *気になる点* 最終的にローマ字の表現のチェックは、以下のようになりました。 if (!ereg("^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \-]*$", $roman)) { この正規表現でちゃんと動作しているのですが「\-」を[]の最後に位置させないと(]の直前)、いくら「\」で「-」をエスケープしていても、エラーになるのです。なぜだかお分かりですか? よろしくお願いします。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

> ローマ字で文字と文字の間の空白を許可するには、何を使用すればよいのですか?、 莫迦正直に列挙するよりないと思いますが。 [ \t\r\n] あたり? > ただ、正規表現でチェックする値が2バイトレターではないのでmb_ereg使うのは、おかしいですよね? まあpreg 使うのがいいんでしょうかね。 mb_とちがってphp.iniをいじらないでも使えるはずですし、扱う正規表現の範囲としては これが一番強力でしょうから。 >if (!ereg("^([a-zA-Z0-9])+([a-zA-Z0-9\.-&,'\s])*$", $roman)) { すでに書いたようにeregは \s なるメタ文字を認識しませんから、 ^[a-zA-Z0-9]+[a-zA-Z0-9.-&, \t]*$ というところでしょうか。 見たところ、丸カッコをここで使う必要はないと思います。 また、[]の中では '.' はピリオドであり、任意の一文字にマッチするメタ文字ではありませんので エスケープの必要はありません。 逆に-をエスケープしとかないとエラーになりませんか? コード順で言うと '.' > '&' なので。 PHP Warning: Wrong parameter count for ereg() in c:\work\sample.php on line 2

kitty1000
質問者

補足

sakusaker7さん ご回答ありがとうございました。 その1: 半角の空白と全角の空白をどのようにして別々に判別するかお分かりですか?ereg内での「\t」が半角空白で、mb_ereg又はpreg内では「\t」が半角空白及び「\s」が全角空白の正規表現ということになるのですかね? その2: また、正規表現の判定にpregを使用する場合でも、判定内容が漢字などの2バイト文字の場合、mb_regex_encodingで正規表現用文字コードを予め宣言しておく必要があるのでしょうか? よろしくお願いします。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

まず、eregの扱うメタ文字に \s はありません。 次に、eregはマルチバイト文字に対応していませんから、 あ-ん というのは たとえばEUC-JPを使っていたとして 0xa4a2 ~ 0xa4f3ではなく、0xa4 0xa2~0xa4 f3 を表すことになります。 ですから、\sを加える前のパターンでも、対象文字列に"かきくけこ" あたりを食わせるとOKにはならないと思います。 期待通りに動作させるにはこんな感じ? mb_regex_encoding("EUC-JP"); $applicant_kana = "あいうえお かきくけこ"; //if (!ereg("^([あ-ん])+([あ-んー])*$", $applicant_kana)) { if (!mb_ereg("^[あ-ん][あ-んー\s]*$", $applicant_kana)) { echo 'ふりがなエラー'; } else { echo 'ふりがなOK'; } eregでもやってやれなくはありませんがそれはおいときます。

kitty1000
質問者

補足

sakusaker7さん ご回答ありがとうございました。 その1: >まず、eregの扱うメタ文字に \s はありません。 それでは、ローマ字で文字と文字の間の空白を許可するには、何を使用すればよいのですか?、こちらも「This is a pen」と入力した場合(文字と文字の間に”全角空白”ではなく”半角空白”がある場合)に「ローマ字OK」と表示させたいのです。文字と文字の間に”全角空白”がある場合は、ローマ字エラーです。 つまり、 「This」→ローマ字OK 「This is a pen」→ローマ字OK 「This is a pen」→ローマ字エラー 下記が私の現在のコードですが、 if (!ereg("^([a-zA-Z0-9])+([a-zA-Z0-9\.-&,'\s])*$", $roman)) { echo 'ローマ字エラー'; } else { echo 'ローマ字OK'; } こちらも mb_regex_encoding("UTF-8"); if (!mb_ereg("^([a-zA-Z0-9])+([a-zA-Z0-9\.-&,'\s])*$", $roman)) { echo 'ローマ字エラー'; } else { echo 'ローマ字OK'; } などでよいのでしょうか?ただ、正規表現でチェックする値が2バイトレターではないのでmb_ereg使うのは、おかしいですよね? だいたい半角の空白と全角の空白をどのようにして別々に判別するのか自体、理解していませんが。 その2: ふりがなの方は、下記でちゃんと動作しました。 このあともう少し検証してみます。 mb_regex_encoding("UTF-8"); if (!mb_ereg("^[あ-ん][あ-んー\s]*$", $applicant_kana)) { echo 'ふりがなエラー'; } else { echo 'ふりがなOK'; } よろしくお願いします。

すると、全ての回答が全文表示されます。

関連するQ&A