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

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

ただいまの
回答率

90.12%

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,330

holic

score 112

 前提・実現したいこと

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

$targetText = <<<EOT
200
300
400
EOT;

$targetText = preg_replace('/1|299/',0,$targetText);
echo $targetText;

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • maisumakun

    2018/03/21 16:20 編集

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

    キャンセル

  • maisumakun

    2018/03/21 16:20

    そして、300は0にすればいいのでしょうか、1にすればいいのでしょうか。

    キャンセル

  • m6u

    2018/03/21 16:42

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

    キャンセル

  • holic

    2018/03/21 17:03

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

    キャンセル

回答 4

checkベストアンサー

+2

<?php

$targetText = <<<EOT
200
300
400
EOT;

$data = explode("\n", $targetText);

foreach ($data as $val) {
    if (intval($val) < 300) {
        echo '0' . "\n";
    } else {
        echo '1' . "\n";
    }
}


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

<?php

$targetText = <<<EOT
0
1
2
3
10
20
30
100
200
300
900
EOT;

$data = explode("\n", $targetText);

foreach ($data as $val) {
    if (preg_match("/^[012][0-9]{0,2}$/", $val) || preg_match("/^[3-9][0-9]?$/", $val) ) {
        echo '0' . "\n";
    } else {
        echo '1' . "\n";
    }
}

0
0
0
0
0
0
0
0
0
1
1

preg_replace()使ってみると

<?php

$targetText = <<<EOT
0
1
2
3
10
20
30
100
200
300
900
EOT;

$patterns     = array("/^[12][0-9]{2}$/m", "/^[3-9][0-9]{2}$/m", "/^[1-9][0-9]$/m", "/^[0-9]$/m");
$replacements = array('A', 'B', 'A', 'A');
$patterns_2nd = array('/^A$/m', '/^B$/m');
$replacements_2nd = array('0', '1');

$targetText = preg_replace($patterns, $replacements, $targetText);
$targetText = preg_replace($patterns_2nd, $replacements_2nd, $targetText);

echo $targetText;

0
0
0
0
0
0
0
0
0
1
1

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/21 18:30

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

    キャンセル

+2

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

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

  • 2段階
<?PHP
$targetText = <<<EOT
1
10
99
100
200
299
300
301
400
800
899
900
901
1000
EOT;

$targetText = preg_replace('/^([0-9]|[1-9][0-9]|[12][0-9]{2}|300)$/m',0,$targetText);
$targetText = preg_replace('/^([3-8][0-9]{2}|900)$/m',1,$targetText);
echo $targetText;
  • callback
$targetText = <<<EOT
1
10
99
100
200
299
300
301
400
800
899
900
901
1000
EOT;

$targetText = preg_replace_callback('/^[0-9]{1,3}$/m',function($x){
  $ret=$x[0];
  if($ret<=300){
    $ret=0;
  }elseif($ret<=900){
    $ret=1;
  }
  return $ret;
},$targetText);
echo $targetText;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/22 16:33

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

    キャンセル

  • 2018/03/22 16:50

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

    キャンセル

  • 2018/03/23 00:09 編集

    家に帰って、家のアパッチ環境でも試しましたが、やはりだめでした。
    ダメというのは、「変換されないまま表示」という意味です。

    試しに
    <?PHP
    $targetText = <<<EOT
    1
    10
    99
    100

    EOT;

    の部分を

    <?PHP
    $targetText = 300;

    にしたら正しく変換してくれました。
    <<<EOTの書き方に問題があるのでしょうか。

    キャンセル

+1

お試しでやってみたw

<?php
$targetText = <<<EOT
111
200
300
301
400
900
EOT;
$patterns = ['/300/', '/[ 12][ \d]{2}/', '/[3-9]\d{2}/'];
$replace = ['0', '0', '1'];
$targetText = preg_replace($patterns, $replace, $targetText);
echo $targetText;


指摘を受けての修正

<?php
$targetText = <<<EOT
0
1
11
111
200
300
301
400
900
EOT;
$patterns = ['/^300$|(?(?=(^\d{1,2})$)\d{1,2}$|^[12][\d]{2}$)/m', '/^[3-9]\d{2}$/m'];
$replace = ['0', '1'];
$targetText = preg_replace($patterns, $replace, $targetText);
echo $targetText;

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/21 18:09 編集

    うちの回答とニコイチすれば良さげ?

    キャンセル

  • 2018/03/21 21:01

    /m PCRE_MULTILINE指定、思い出しました。ありがとうございます。

    キャンセル

  • 2018/03/21 21:57

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

    キャンセル

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

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる