日本PHPユーザ会 掲示板

日本PHPユーザ会運営の掲示板です。※ただいまテスト運用中です。

日本PHPユーザ会 掲示板 » PHP 5 » 正規表現のご相談

正規表現のご相談

ページ: 1

投稿者 投稿
会員
登録者: 9 2008
返信数: 5
はじめて投稿させていただきます。
仕事でPHPとMySQLを使い始めたのですが、DBから取得したテキスト文字列のなかに含まれる数字を数字が1桁なら全角に、2桁以上なら半角にしなければならないのですが、これを簡単に実現できる方法等ご存知の方いらっしゃいませんでしょうか?
mbereg_replaceでいろいろやってはみたものの、置換文字列が1文字ではないため、1文字ずつ取りだして比較していくしかないのかなぁと思っています。。。
会員
登録者: 9 2008
返信数: 3
1.すべて全角にする
2.正規表現で二文字以上のものだけ半角にする
って手順でできませんか?
全角と半角はもちろん逆でも良いのですが、正規表現では1桁を表現するより2桁以上を表現するほうが容易です
会員
登録者: 9 2008
返信数: 3
上の発言は無視してくださいorz
文字コードがスクリプトとデータベースで同じと仮定してですが、preg_replace_callback一発がベターですね
pregシリーズはバイナリーデータに対応しているので123がそのまま使えます。
とはいえ文字コードによってはいろいろ複雑なものがあるようですが・・・
preg_replace_callback("/(?:\d|0|1|2|3|4|5|6|7|8|9)+/", 'callback', ....)
function callback($match)
{
if (....
}

http://jp.php.net/manual/ja/function.preg-replace-callback.php
http://jp.php.net/manual/ja/regexp.reference.php
会員
登録者: 10 2007
返信数: 71
(まだ試してないのですが)もし自分がやるとしたら、
(1) 一旦、mb_convert_kana()で数字だけを全部半角にしておく。
(2) preg_replace()e修飾子指定で、「1桁の数字」をmb_convert_kana()で全角にして置換する。
という方法ですが、どうでしょうか。

adachiさんのおっしゃる通り、内部文字エンコーディングがUTF-8かEUC-JPならば、全角文字でもpregシリーズが使えてしまうみたいですね。
会員
登録者: 9 2008
返信数: 3
e修飾子なんてのがあったのか・・・これは便利ですね
勉強になります
会員
登録者: 9 2008
返信数: 5
みなさん、ご回答ありがとうございます。

callbackについては、書籍等にも正規表現とか軽くさわる程度しかのっていなかったりして、よくわかっていませんが少し時間のあるときにいろいろためしてみようと思います。

いまの環境は元データがUnicode文字が含まれておりましたので、UTF-8でDB構築しており、内部エンコーディングもすべてUTF-8となっております。

わたしもkona@mさんのようにmb_convert_kanaで数字だけ全部半角にしてからと考えていたのですが、置換文字列をどうしたものか頭を悩ませておりました。preg_replace なんて関数あったんですね。。。知りませんでした(mb_ereg_replaceでなんとかしようとしてました)。e修飾子についても知らなかったので少し調べてみます。
後日、結果をご連絡したいと思います。

また、じつはもう1ついま悩んでいるところがあって、日本語文である文章のなかに句読点があって、これらを全角にしなければならないのですが、数字の桁区切りは半角でなくてはならないのです。
それで、MIFES とかで調べて以下だと置換できたのですが、PHPだと思った通りにならない状態です。いまいちPHPでの正規表現の書き方がよくわかっていないので、地方に住んでるので書籍を取り寄せ注文していて届くまではなんとか試行錯誤しないといけません。

検索文字列:{[0-9]+}{[,]}{[0-9]+}
置換文字列:\1,\3

PHP では以下のようにしてみたのですが、なにか書き方が違うのでしょうか?

$data = mb_ereg_replace("{[0-9]+}{[,]}{[0-9]+}", "\\1,\\3", $data);

正規表現で難しいですね。。。仕事が一段落したらちゃんと覚えなおさないといけないなと思ってるところです。
会員
登録者: 9 2008
返信数: 5
すみません、さきほどの数字の桁区切りのカンマは以下のようにして自己解決しました。

$string = "1,200件以上";
$pattern = '/(\d+),(\d+)/';
$replacement = '${1},$2';
echo preg_replace($pattern, $replacement, $string);

1桁数字の全角、2桁以上半角にするほうがんばってみま・x・
会員
登録者: 10 2007
返信数: 71
思ったより試行錯誤してしまいましたが、こんな感じでできました。

$s = '0)テスト123です。1と2と345です。999';

$s = mb_convert_kana($s, 'n');
$s = preg_replace('/(^|\D)(\d)(\D|$)/e', '"$1".mb_convert_kana("$2", "N")."$3"', $s);

echo $s;

いかがでしょうか?
(先頭または数字以外)と(末尾または数字以外)にはさまれた(1文字の数字)を検索し、変換して置換します。この時(先頭または数字以外)と(末尾または数字以外)も置換対象になってしまうので、そのまま数字の前後にくっつけて返すのがポイントです。

それと、前の私の投稿で「全角文字でもpregシリーズが使えてしまう」と書きましたが、「全角文字でも工夫次第でpregシリーズが使えてしまう」に訂正させて下さい。
確か /[あいう]/ はうまくいかなくて /[(あ)(い)(う)]/ にする必要があります。日本語だと1文字に見えても実際には2バイト以上の並びとして扱う必要があるようです。
その点、mb_eregシリーズの利点が見えてきます。(私はあまり使ったことがないので詳しくないのですが。)
会員
登録者: 9 2008
返信数: 5
kona@m さん、ありがとうございます。

正規表現の「(先頭または数字以外)と(末尾または数字以外)も置換対象になってしまう」というところがよくわからなかったのですが、数字以外で挟まれた場合はイメージがつくのですが、先頭と末尾に関してはなぜ変換対象となるのかがどういう動作原理なんだろうと思ってしまいました。
$1と$3が先頭と末尾だと思うのですが、いろいろ考えたのですがよくわかりませんでした。

とりあえずいただいたコードをテストしてうまくいっていることが確認できましたのでとても助かりました。ただ、文字列のなかで句読点「、。」は半角・全角問わず「,。」の全角文字に変換しなくてはならず、3桁数字のものは半角にしなくてはなりませんでしたので以下のコードにしてみました。

$string = "小学校5,6年1,200名以上のなかから50人を選出する。";

$string = mb_convert_kana($string, "n");

$string = mb_ereg_replace(",", ",", $string);
$pattern = '/(\d+),(\d{3})/';
$replacement = '$1,$2';
$string = preg_replace($pattern, $replacement, $string);

$pattern = '/(^|\D)(\d)([^0-9,]|$)/e';
$replacement = '"$1".mb_convert_kana("$2", "N")."$3"';
$string = preg_replace($pattern, $replacement, $string);

print $string."<br>";

なんか効率が悪いような気もしますが、このような感じでだいじょぶでしょうか?テストして問題はなさそうですがあまり自身ないです。また、もっとスリムにできそうなコードであれば助言いただければ嬉しいです。

ページ: 1

日本PHPユーザ会 掲示板 » PHP 5 » 正規表現のご相談

日本PHPユーザ会 掲示板 は UseBB 1 フォーラムソフトウェア を使用しています