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

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

ただいまの
回答率

90.61%

  • PHP

    19817questions

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

  • 正規表現

    776questions

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

正規表現で特定文字1文字の場合のみマッチする書き方

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 2,156

kitsunekonkon

score 21

phpのpreg_match関数で

あいうえお!!

かきくけこ!?

などの感嘆符、疑問符ひとつ以上の時はマッチせず、

あいうえお!
かきくけこ?

など感嘆符、疑問符がひとつだけのときはマッチする

という条件でif文で判定したいのですが、

preg_match('/[!\?]?/', $string)

で感嘆符や疑問符ひとつだけの時を判定しようとしても

あいうえお!

のような文字列に引っかかってくれません。

特定の文字がひとつだけの場合は引っかかり、2つ以上連続するときは引っかからないような正規表現はどのように書いたらよろしいでしょうか??
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

0

こんな感じでどうでしょう?

対象の文字列に「感嘆符、疑問符が一つだけの部分文字列」が含まれていればマッチし、
マッチした場合は、見つかった文字列を配列として取得します。

<?php

$data = array(
  "", "!", "&", "!!", "&&", "!!!", "&&&",
  "あいうえお!",
  "あいうえお?",
  "あいうえお!!",
  "あいうえお!?",
  "あいうえお??",
  "あいうえお?!",
  "あいうえお???",
  "あいうえお!??",
  "あいうえお?!?",
  "あいうえお??!",
  "あいうえお!!!",
  "あい!うえ!!おかき!?くけこさ?しすせそ",
  "!あいうえお!",
  "!あいうえお!!"
);

foreach($data as $subject) {
  print "=== string : {$subject} ===" . PHP_EOL;
  $pattern = "/(?![^!?]+([!?]{2,}))[^!?]+[!?]/";
  if (preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER)) {
    print_r($matches);
  }
}

正規表現部分の説明です。
$pattern = "/(?![^!?]+([!?]{2,}))[^!?]+[!?]/";

前半の「(?![^!?]+([!?]{2,}))」が否定先読みにより
「後ろに感嘆符か疑問符の組み合わせを二つ以上持つ、感嘆符、疑問符を含まない文字列」
をマッチさせないようにして、

後半の「[^!?]+[!?]」により
「後ろに感嘆符か疑問符を一つ持つ、感嘆符と疑問符を含まない文字列」
にマッチさせるようにしています。

簡単なテストデータなのでバグがないとも言い切れませんが、
参考になれば幸いです。

※補足
正確には先読みや否定先読みは位置にマッチするので、今回の正規表現は、
「後ろに感嘆符か疑問符の組み合わせを二つ以上持つ、感嘆符、疑問符を含まない文字列」
にマッチしない位置を表し、その位置と後半の正規表現を合わせた条件になるようです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/10/06 13:12

    StupidDog様

    お返事遅れてしまって大変申し訳ございません。
    記載していただいた通りの正規表現で意図通りのプログラムがかけました!
    ありがとうございます。またこちらの回答をベストアンサーにさせていただきます。
    本当に助かりました。

    キャンセル

0

PCREには、言明という機能があって、「あとに特定のパターンが続かない」ことを(?!パターン)の形で宣言できます。

//あとに同種の記号が続かない感嘆符・疑問符にヒット
preg_match('/[!?](?![!?])/', $string)

なお、角カッコ内での特殊文字は、閉じ角カッコ以外エスケープ不要です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/09/30 17:55

    ありがとうございます!

    教えていただいたように下記のようなコードで試してみましたが、なぜか感嘆符が連続している場合にも引っかかってしまいます。

    以下が実行してみたコードです。

    ```
    <?php
    if (preg_match('/[!?](?![!?])/', 'あいうえお!!')) {
    echo 'マッチしました。';
    } else {
    echo 'マッチしませんでした。';
    }
    ```

    結果
    ```
    マッチしました。
    ```
    どこか書き方が間違っているのでしょうか?
    ご教示いただけると助かります。

    よろしくお願いします。

    キャンセル

0

maisumakun様の回答では、連続している"!?"のうち、一番後ろの"!?"がマッチしてしまいます。

質問者様の意図として、
文字列の末尾の"!?"だけをチェックしたい(文字列の途中に"!?"が含まれる場合は考慮しない)
のであれば、
以下の正規表現で実現できると思います。

/[^!?][!?]$/

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/09/30 18:47

    KiyoshiMotoki様

    ありがとうございます!
    文字列末尾の!や?だけをチェックすることでほとんどの場合は問題ないかと思いますが、
    純粋に文中にも末尾にも!や?が存在する場合に

    連続してたらマッチしない。
    ひとつだけならマッチする。

    という条件で判定する場合はどのようになりますでしょうか?

    このような場合正規表現で全てを一気に判定するよりも、文中の場合と文字列末尾の場合で条件を分けて記述したほうが、簡単でしょうか?

    キャンセル

  • 2015/09/30 19:48 編集

    文中の"!?"もチェックしたい場合は、以下のようになります。
    ```php
    /(^|[^!?]*)[!?]([^!?]*|$)/
    ```

    ただし、2点問題があり、

    1.
    この場合は
    複数箇所に分かれて"!"または"?"が現れた場合にもマッチしてしまいます。
    (文中にただ1回だけ"!"または"?"が現れるのを許容する、という要件に対応できない)

    ```php
    $string = 'あいうえお! かきくけこ?';
    preg_match('/(^|[^!?]*)[!?]([^!?]*|$)/', $string); // マッチする
    ```

    それで問題ないなら構わないですが、そうでないなら`substr_count`または`mb_substr_count`で"!"と"?"の出現回数を調べた方が簡単だと思います。

    http://php.net/manual/ja/function.substr-count.php
    http://php.net/manual/ja/function.mb-substr-count.php

    2.
    ちゃんと動作確認していませんw

    キャンセル

  • 2015/09/30 20:14

    KiyoshiMotoki様

    なるほど!文中の中で使う場合は制約が出てしまうのですね。
    とりあえず教えていただいた方法で試してみます。

    意図した通りにいかないようであれば、mb_substrなどを使ってやってみます!
    ありがとうございました(^^)

    キャンセル

0

否定先読み、否定戻り読みを使ってこういうのどうでしょう?
<?php
if (preg_match('/(?<! [!?])[!?](?![!?])/', 'あいうえお!!')) echo '1にマッチしました。';
if (preg_match('/(?<! [!?])[!?](?![!?])/', 'あいうえお!')) echo '2にマッチしました。';
?>
//teratail上での表示が壊れるので、?<![!?] の!と[の間にスペースを入れています。
所で感嘆符にだけHITすればよかったのでしょうか?
コード中の2でHITしているのは「あいうえお!」ではなくて、「!」です
単独の感嘆符が存在するかどうかを判定ですだけならいいのですが、
HITする部分を抽出して処理する場合不十分かも知れません

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/09/30 20:39

    否定先読み投稿すると表示がバグる?
    画像添付のコードと被ってるのかも知れません。修正中

    キャンセル

  • 2015/10/01 11:12

    hirohiro様
    ありがとうございます。否定先読み、戻り読みというもの自体初めて知りました。
    勉強になります。
    hirohiro様のおっしゃるとおり、HITする部分を抽出する必要があるので、少し修正する必要がありそうです。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る

  • PHP

    19817questions

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

  • 正規表現

    776questions

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