質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

4回答

3249閲覧

php preg_replaceで数値の範囲を正規表現で指定して置換

holic

総合スコア134

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2018/03/21 07:14

編集2018/03/21 08:02

前提・実現したいこと

phpの置換関数 preg_replaceを使ってある範囲内の数値を置換したいのです。
下記に例題を記します。
●数値「1」~「300」までの範囲の数値を全て数値「0」に変えたい。
そして「301」~「900」までの範囲の数値を全て数値「1」に変えたい。

php

1$targetText = <<<EOT 2200 3300 4400 5EOT; 6 7$targetText = preg_replace('/1|299/',0,$targetText); 8echo $targetText;

正規表現の使い方がうまくいかずです、
phpに詳しい方、正しく動くソースをご教示願いますでしょうか、よろしくお願いいたします。

【追記】
●題名を[preg_replace]を使ってとしましたが、すっきりと解決ができるのでしたら、違う関数でも問題ございません。
●文字列は絶対に数字となります。数字の範囲は1~900です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2018/03/21 07:20 編集

どうしても「preg_replace」でないといけない理由はありますでしょうか(別な方法のほうがすっきり書けるようにも思える場面です)。
maisumakun

2018/03/21 07:20

そして、300は0にすればいいのでしょうか、1にすればいいのでしょうか。
退会済みユーザー

退会済みユーザー

2018/03/21 07:42

実際の入力は数字の前後に余計な文字列も含まれる可能性がある、という意味でしょうか?
holic

2018/03/21 08:03

たくさんのご意見ありがとうございます。追記しました。「preg_replace」にはこだわりません。
guest

回答4

0

2段階で処理するか、callbackで

  • 2段階

PHP

1<?PHP 2$targetText = <<<EOT 31 410 599 6100 7200 8299 9300 10301 11400 12800 13899 14900 15901 161000 17EOT; 18 19$targetText = preg_replace('/^([0-9]|[1-9][0-9]|[12][0-9]{2}|300)$/m',0,$targetText); 20$targetText = preg_replace('/^([3-8][0-9]{2}|900)$/m',1,$targetText); 21echo $targetText;
  • callback

PHP

1$targetText = <<<EOT 21 310 499 5100 6200 7299 8300 9301 10400 11800 12899 13900 14901 151000 16EOT; 17 18$targetText = preg_replace_callback('/^[0-9]{1,3}$/m',function($x){ 19 $ret=$x[0]; 20 if($ret<=300){ 21 $ret=0; 22 }elseif($ret<=900){ 23 $ret=1; 24 } 25 return $ret; 26},$targetText); 27echo $targetText; 28

投稿2018/03/22 04:03

yambejp

総合スコア114574

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2018/03/22 04:05

ちなみにcallbackの方は数字の整合性をとってません たとえば001とか099とかも数値としてチェックしてしまいます
holic

2018/03/22 05:47

ありがとうございます。 php 初心者の私にとって2段階で十分でございます。 補足で説明をお願いしたいところがございます。 /^([0-9]|[1-9][0-9]|[12][0-9]{2}|300)$/ はじめの「^」 最後の「$」 を付与させている意味を教えていただいてもよろしいでしょうか。 「^」は最初がコレで始まる 「$」は最後がコレで終わるのいみですよね、2ついっぺんに使うところを見たことがなかったので。
yambejp

2018/03/22 05:53 編集

/^([0-9]|[1-9][0-9]|[12][0-9]{2}|300)$/の説明 ^(...)$→行の先頭から末尾まで 0から9まで→[0-9] 10から99まで→[1-9][0-9] 100から199までと200から299まで=100から299まで→[12][0-9]{2} それに300 これを「|」でつなぐとorになるので 0から300までという意味になります
holic

2018/03/22 06:06

詳細な補足説明ありがとうございます。 大変参考になりました。 深く感謝いたします。
holic

2018/03/22 06:11

「2段階」のほうを試してみたのですが(そのままソースをコピペ)でしたが、上手く動きませんでした。
yambejp

2018/03/22 06:59

> そのままソースをコピペ)でしたが、上手く動きませんでした うーん、何でしょね PHPのバージョンかもしれません、当方PHP5.6系で処理しています
holic

2018/03/22 07:33

アパッチ環境で実施して上手く動きませんでした。 念のため、PHP 7.1系のさくらサーバーにアップしましたが、同じようにだめでした。
yambejp

2018/03/22 07:50

ちなみにダメというのはエラーなのでしょうか? それとも変換されないまま表示されるのでしょうか?
holic

2018/03/22 15:16 編集

家に帰って、家のアパッチ環境でも試しましたが、やはりだめでした。 ダメというのは、「変換されないまま表示」という意味です。 試しに <?PHP $targetText = <<<EOT 1 10 99 100 ~ EOT; の部分を <?PHP $targetText = 300; にしたら正しく変換してくれました。 <<<EOTの書き方に問題があるのでしょうか。
guest

0

ベストアンサー

php

1<?php 2 3$targetText = <<<EOT 4200 5300 6400 7EOT; 8 9$data = explode("\n", $targetText); 10 11foreach ($data as $val) { 12 if (intval($val) < 300) { 13 echo '0' . "\n"; 14 } else { 15 echo '1' . "\n"; 16 } 17}

で、ちゃんとpreg_match()を使うと

php

1<?php 2 3$targetText = <<<EOT 40 51 62 73 810 920 1030 11100 12200 13300 14900 15EOT; 16 17$data = explode("\n", $targetText); 18 19foreach ($data as $val) { 20 if (preg_match("/^[012][0-9]{0,2}$/", $val) || preg_match("/^[3-9][0-9]?$/", $val) ) { 21 echo '0' . "\n"; 22 } else { 23 echo '1' . "\n"; 24 } 25}

0
0
0
0
0
0
0
0
0
1
1

preg_replace()使ってみると

php

1<?php 2 3$targetText = <<<EOT 40 51 62 73 810 920 1030 11100 12200 13300 14900 15EOT; 16 17$patterns = array("/^[12][0-9]{2}$/m", "/^[3-9][0-9]{2}$/m", "/^[1-9][0-9]$/m", "/^[0-9]$/m"); 18$replacements = array('A', 'B', 'A', 'A'); 19$patterns_2nd = array('/^A$/m', '/^B$/m'); 20$replacements_2nd = array('0', '1'); 21 22$targetText = preg_replace($patterns, $replacements, $targetText); 23$targetText = preg_replace($patterns_2nd, $replacements_2nd, $targetText); 24 25echo $targetText;

0
0
0
0
0
0
0
0
0
1
1

PHP: 正規表現パターンに使用可能な修飾子 - Manual
/mで複数行データでもヒットするようになります。

投稿2018/03/21 08:43

編集2018/03/21 12:05
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/21 09:30

preg_replace()って、配列で与えた$patternsを順に必ず評価して置換していくので、 0や1に置換したあと、4つ目のパターンで必ずヒットして0になっちゃうから、 一度AとかBとか数字じゃないものに置き換えてから 再度0や1に置き換えてみた次第。
guest

0

どう考えても正規表現での置換を使うべき題材ではありません。forループと比較演算子とifで対処してください。

投稿2018/03/21 07:39

KojiDoi

総合スコア13669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

お試しでやってみたw

php

1<?php 2$targetText = <<<EOT 3111 4200 5300 6301 7400 8900 9EOT; 10$patterns = ['/300/', '/[ 12][ \d]{2}/', '/[3-9]\d{2}/']; 11$replace = ['0', '0', '1']; 12$targetText = preg_replace($patterns, $replace, $targetText); 13echo $targetText;

指摘を受けての修正

php

1<?php 2$targetText = <<<EOT 30 41 511 6111 7200 8300 9301 10400 11900 12EOT; 13$patterns = ['/^300$|(?(?=(^\d{1,2})$)\d{1,2}$|^[12][\d]{2}$)/m', '/^[3-9]\d{2}$/m']; 14$replace = ['0', '1']; 15$targetText = preg_replace($patterns, $replace, $targetText); 16echo $targetText;

投稿2018/03/21 09:04

編集2018/03/21 12:57
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/21 09:06

PCRE正規表現記述箇所に、行頭一致や行末一致の^とか$があったほうがより安全な気がします。
退会済みユーザー

退会済みユーザー

2018/03/21 09:07

これ、二桁以下ダメだな^^;
退会済みユーザー

退会済みユーザー

2018/03/21 09:10 編集

うちの回答とニコイチすれば良さげ?
退会済みユーザー

退会済みユーザー

2018/03/21 12:01

/m PCRE_MULTILINE指定、思い出しました。ありがとうございます。
退会済みユーザー

退会済みユーザー

2018/03/21 12:57

修正版、ちょっと恥ずかしい感じだったので差し替えました^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問