dポイントプレゼントキャンペーン実施中!

PHPで、「文字列の前後に付加されている全角空白/半角空白/改行文字を取り除く」
という処理をしたいのですが、以下のように置換処理を書くとうまくいきません。

$after = preg_replace('/^[  \r\n]*(.*)[  \r\n]*$/u', '$1', $before);
// [  \r\n]→[半角空白、全角空白、改行文字]です

どううまくいかないのかといいますと、入力として半角スペース+全角文字が入ったときに、全角文字の先頭文字が文字化けしてしまいます。

たとえば、
<半角スペース>あああ
をこれにかけると、
<よくわからない文字>ああ
となります。

以下のように2回に分けてみると、正常に動きます。
$tmp = preg_replace('/[  \r\n]*$/u', '', $before);
$after = preg_replace('/^[  \r\n]*/u', '', $tmp);

最初のように1回の正規表現による置換で済ませたい場合、
どのように書くのが適切なのでしょうか?

PHPのバージョンは5.2.3です。

A 回答 (6件)

preg_replaceはマルチバイトに対応していません。


全角半角は 81 40 なので、それに該当したバイトコード全てを削除しようとします。
「あ」は82 A0なので文字化けはしないと思いますが・・・
「@」(40)が先頭にあったり、81で始まるマルチバイト文字が先頭にある場合は文字化けすると思われます。

正規表現をそのままにmb_ereg_replace()を使うと良いと思われます。

>trim()
マルチバイトでは正常に動かないんじゃないかなぁ。
試してないので分かりませんが。

この回答への補足

preg_replace試してみました。
$after = mb_ereg_replace('^[  \r\n]*(.*?)[  \r\n]*$', '\1', $before);

結果:
<入力>
ああ
<出力>
??ああ

あれれ・・・
回答を即座にいただいて喜び勇んでやってみたのですが、
うまくいかず・・・どこか間違っているでしょうか??

補足日時:2008/04/24 17:26
    • good
    • 0
この回答へのお礼

お礼に記載して申し訳ないのですが、訂正します

結果:
<入力>
ああ
<出力>
??あ

です。大変失礼しました。

お礼日時:2008/04/24 17:31

$after = preg_replace('/^[  \r\n]*(.*?)[  \r\n]*$/u', '$1', $before);


でも、
$after = mb_ereg_replace('^[  \r\n]*(.*?)[  \r\n]*$', '\1', $before);
でも、きれいに置換され、
文字化けを再現することはできませんでしたが、
↓preg_replaceでuをつけ忘れたときだけ、「??ああ」となりました。
$after = preg_replace('/^[  \r\n]*(.*?)[  \r\n]*$/', '$1', $before);
実行環境でuが抜けているということはないでしょうか。

この回答への補足

続きですが当方の環境では以下のようになっているようです。

あ:e3 81 82
全角スペース:e3 80 80
半角スペース:20
\r:5c
\n:6e

置換時に指定する文字列として、全角スペースの"e3 80 80"が"e3"として解釈されてしまい、正常に動かないものと考えられます。
現在、3バイトでも置換する方法を調べているところです。

mb_ereg_replaceで可能なのか、他に関数が用意されているのか、
それとも自作するしかないのでしょうか・・・

補足日時:2008/04/25 10:27
    • good
    • 0
この回答へのお礼

訂正いたします:

あ:e3 81 82
全角スペース:e3 80 80
半角スペース:20
\r:5c 72
\n:5c 6e

またまたお礼欄を利用して訂正いたしますことご容赦ください

お礼日時:2008/04/25 10:29

oopsあれー?


と思ったけどよく考えたら当方の環境はEUCだったorz
平にご容赦。そして多謝。

>$after = mb_ereg_replace('^[  \r\n]*(.*?)[  \r\n]*$', '\1', $before);
これで大丈夫な気はしますけどね。
$afterにunpack()噛ましてみて、??に化けている部分にどんなコードが入っているか確認すると原因が分かるかもしれません。
// 今手元に環境がないゆえ、確認できず

$after = mb_ereg_replace('^[  \r\n]*(.*?)[  \r\n]*$', '\1', $before);
$after_arr = unpack("C*",$after);
foreach ($after_arr as $char_dec) { echo dechex($char_dec) . " ";}

こうすると$afterの中身がバイナリ形式で分解され、16進数表示されます。
// 今手元に環境がないゆえ、typoあったら容赦
先頭のバイナリが不正でなければ、mb_ereg_replace()ではなく別に原因があることになります。
先頭にゴミが入っていれば、正規表現にもう一工夫する必要があるかと。


/// だれかズバッとした答えを書いてくれないかなぁ(:>^

この回答への補足

続けての回答ありがとうございます。
試してみたところ、以下のような出力が得られました。

「あ」置換前>あ:e3 81 82
「あ」置換後>??:81 82
「ああ」置換前>ああ:e3 81 82 e3 81 82
「ああ」置換後>??あ:81 82 e3 81 82

e3ってなんだよってところでしょうか…
というか入力が3バイトな気がします

PHPソースはUTF-8で、サーバー環境もUTF-8で統一しております。
入力文字列はブラウザ経由なのでSJISだと思っていましたが3バイト…?当方の知識不足でよくわかりません、すいません。

補足日時:2008/04/25 09:58
    • good
    • 0
この回答へのお礼

質問締め切り後のお礼文です。

以下のコードで意図した通り動くようになりました。

mb_regex_encoding('UTF-8');
$after = mb_ereg_replace('^[  \r\n]*(.*?)[  \r\n]*$', '\1', $before);

基本的なところで詰まっていたようで、encodingの種類を指定することで動くようになりました。
preg_replaceによる置換はうまくいくかと思いきや、改行コードや半角スペースを織り交ぜてテストしてみるとうまくいかないことがありますので、こちらが最終形なのではないかと思っております。

皆様ありがとうございました。
特に何度も回答いただいたwp_さんには感謝です。

お礼日時:2008/04/25 11:06

NO3さんtrim( )はだめなようです


私の環境では@も消えちゃいましたよ
PHP5.2.3で文字コードはsjisです
実行結果
    @@@@test@@@@    
test

この回答への補足

皆さんありがとうございます。
おっしゃるとおり、trimでは全角未対応ということでほかの方法を探しております。
私の環境も入力文字列がSJISとなっており、trimでは正常に動作しない状態です。

補足日時:2008/04/24 17:24
    • good
    • 0

typoした...orz


>全角半角
全角空白ですな。

罪滅ぼしといってはナンですが、trim()調べました。
結論から述べると「いけそうです」
trim()を使うのが手軽で良いかもしれません。

$str = "    @@@@test@@@@    "; // 全角空白あり
echo $str."<br />";
echo trim($str," ");



    @@@@test@@@@    ←全角空白がある状態
@@@@test@@@@←trim()を噛んだ状態

この回答への補足

進展はしていませんが、\マーク1つだとまずいらしく、\\に置き換えて
テストしてみた結果を報告します。


$after = mb_ereg_replace('^[  \\r\\n]*(.*?)[  \\r\\n]*$', '\1', $before);

結果:
<入力>
ああ
<出力>
??ああ

変わりませんでした。むむ・・・

補足日時:2008/04/24 17:38
    • good
    • 0

trimではダメですか?



↓trimの仕様
http://www.php.net/manual/ja/function.trim.php
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!