phpのpreg_match関数で
あいうえお!!
かきくけこ!?
などの感嘆符、疑問符ひとつ以上の時はマッチせず、
あいうえお!
かきくけこ?
など感嘆符、疑問符がひとつだけのときはマッチする
という条件でif文で判定したいのですが、
preg_match('/[!\?]?/', $string)
で感嘆符や疑問符ひとつだけの時を判定しようとしても
あいうえお!
のような文字列に引っかかってくれません。
特定の文字がひとつだけの場合は引っかかり、2つ以上連続するときは引っかからないような正規表現はどのように書いたらよろしいでしょうか??
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
ベストアンサー
こんな感じでどうでしょう?
対象の文字列に「感嘆符、疑問符が一つだけの部分文字列」が含まれていればマッチし、
マッチした場合は、見つかった文字列を配列として取得します。
php
1<?php 2 3$data = array( 4 "", "!", "&", "!!", "&&", "!!!", "&&&", 5 "あいうえお!", 6 "あいうえお?", 7 "あいうえお!!", 8 "あいうえお!?", 9 "あいうえお??", 10 "あいうえお?!", 11 "あいうえお???", 12 "あいうえお!??", 13 "あいうえお?!?", 14 "あいうえお??!", 15 "あいうえお!!!", 16 "あい!うえ!!おかき!?くけこさ?しすせそ", 17 "!あいうえお!", 18 "!あいうえお!!" 19); 20 21foreach($data as $subject) { 22 print "=== string : {$subject} ===" . PHP_EOL; 23 $pattern = "/(?![^!?]+([!?]{2,}))[^!?]+[!?]/"; 24 if (preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER)) { 25 print_r($matches); 26 } 27}
正規表現部分の説明です。
php
1$pattern = "/(?![^!?]+([!?]{2,}))[^!?]+[!?]/";
前半の「(?![^!?]+([!?]{2,}))」が否定先読みにより
「後ろに感嘆符か疑問符の組み合わせを二つ以上持つ、感嘆符、疑問符を含まない文字列」
をマッチさせないようにして、
後半の「[^!?]+[!?]」により
「後ろに感嘆符か疑問符を一つ持つ、感嘆符と疑問符を含まない文字列」
にマッチさせるようにしています。
簡単なテストデータなのでバグがないとも言い切れませんが、
参考になれば幸いです。
※補足
正確には先読みや否定先読みは位置にマッチするので、今回の正規表現は、
「後ろに感嘆符か疑問符の組み合わせを二つ以上持つ、感嘆符、疑問符を含まない文字列」
にマッチしない位置を表し、その位置と後半の正規表現を合わせた条件になるようです。
投稿2015/10/01 00:38
編集2015/10/01 12:53総合スコア263
0
否定先読み、否定戻り読みを使ってこういうのどうでしょう?
<?php if (preg_match('/(?<! [!?])[!?](?![!?])/', 'あいうえお!!')) echo '1にマッチしました。'; if (preg_match('/(?<! [!?])[!?](?![!?])/', 'あいうえお!')) echo '2にマッチしました。'; ?> //teratail上での表示が壊れるので、?<![!?] の!と[の間にスペースを入れています。
所で感嘆符にだけHITすればよかったのでしょうか?
コード中の2でHITしているのは「あいうえお!」ではなくて、「!」です
単独の感嘆符が存在するかどうかを判定ですだけならいいのですが、
HITする部分を抽出して処理する場合不十分かも知れません
投稿2015/09/30 11:38
編集2015/09/30 11:54総合スコア2068
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
maisumakun
様の回答では、連続している"!?"のうち、一番後ろの"!?"がマッチしてしまいます。
質問者様の意図として、
文字列の末尾の"!?"だけをチェックしたい(文字列の途中に"!?"が含まれる場合は考慮しない)
のであれば、
以下の正規表現で実現できると思います。
php
1/[^!?][!?]$/
投稿2015/09/30 09:30
総合スコア4791
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
PCREには、言明という機能があって、「あとに特定のパターンが続かない」ことを(?!パターン)
の形で宣言できます。
php
1//あとに同種の記号が続かない感嘆符・疑問符にヒット 2preg_match('/[!?](?![!?])/', $string)
なお、角カッコ内での特殊文字は、閉じ角カッコ以外エスケープ不要です。
投稿2015/09/30 08:05
編集2015/09/30 08:07総合スコア146532
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/10/06 04:12