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

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

ただいまの
回答率

91.35%

  • PHP

    15157questions

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

  • 正規表現

    568questions

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

末尾に来た後の動作は、

受付中

回答 1

投稿 2017/11/28 19:26 ・編集 2017/11/29 18:31

  • 評価
  • クリップ 0
  • VIEW 92

aaaaaaaa

score 413

文字列abcに対して正規表現.*\\\を適用すると…

文字列:△▲abc  正規表現:▲.*\\\
…aが.*にマッチするかどうか調べるが、保存ステートにaが\にマッチするかどうか調べるというバックトラックを保存。aは、.*にマッチするので先に進める。

<中略…bとcもaと同じような動作をする>

文字列:△abc▲ 正規表現:▲.*\\\
…cの後ろの位置(空白文字?)が.*にマッチするか調べるが、保存ステートにcの後ろの位置が\にマッチするか調べるバックトラックを保存。
cの後ろの位置は、.*にマッチする。

ここで質問ですがこのcの後ろの位置が.*にマッチした後の動作がわかりません。
恐らく

文字列:△abc▲ 正規表現:.*▲\\\
…cの後ろの位置が\にマッチするか調べるが、マッチしないので先ほどの保存ステートの末尾から実行していく。

か、

文字列:△abc▲ 正規表現:.*▲\\\
…文字列の末尾に来たが、\にマッチする文字列が無いので保存ステートの末尾から実行していく。

のどちらかだと思うのですが、どうなのでしょうか。

またこのあとの動作についても、バックトラックもマッチしないので△を一つ進め上記の動作を繰り返し、最終的にマッチしないということであっておりますか。

※△がマッチした箇所の開始位置で、▲が正規表現を適用するときの現在の位置とします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

+1

 バックトラック

abcに対して正規表現.*//を適用すると…

/.*\/\//.test('abc');
  1. "/" が後続する正規表現 /.*/ を探す
  2. "abc" まで消費して、"/" が後続しなかったので処理終了

バックトラックは発生しません。

 PHPの文字列構文

$test = preg_replace("/\\\\/","b","\\");
$test1 = preg_replace("/\\\/","b","\\");//なぜ四つでも三つでも合致するのか...

"/\\\\/""/\\\/" が /\\/ と評価される為です。
preg_replace では文字列構文のエスケープシーケンスが必要になるわけですが、エスケープの仕様が独特で、バックスラッシュエスケープはバックスラッシュにしか働きません

phpだと\\は、\\\、\\\\でないと合致できませんでした。(厳密にいうと置換だとワーニングのみだが、合致させるだけならワーニングが表示されつつ合致されている)

警告文が現われたのであれば内容を読んでみて下さい。おそらく、バックスラッシュエスケープに纏わる説明が出力されていると思います。

echo "/\\\\/\n";
echo preg_replace("/\\\\/","b","\\")."\n";
echo "/\\\/\n";
echo preg_replace("/\\\/","b","\\")."\n";

※特定の実装特有の問題のようなので、初めからコードを出して質問をされると良かったと思います。
質問文からは「正規表現の問題」と受け取れますが、結果的には「PHPの文字列構文の扱いの問題」でした。

Re: aaaaaaaa さん

投稿 2017/11/29 08:44

編集 2017/12/04 23:48

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/29 18:33

    ご回答ありがとうございました。質問文に誤りがありましたので修正しました。
    せっかく投稿してくださったのに申し訳ありません。

    キャンセル

  • 2017/11/29 18:56

    > 文字列abcに対して正規表現.*\\\を適用すると…
    \\\ は正しい正規表現ではありません。
    仮に \\\\ と読み替えても、答えは変わらないと考えます。

    キャンセル

  • 2017/11/29 19:25

    ご返答ありがとうございます。
    https://qiita.com/uessy_akr/items/b8d3f08032af5725bcb1
    や、詳説正規表現の186頁にて
    "
    Windowsのファイル名用のコードも示す。windowsは、スラッシュではなく、バックスラッシュを区切り子としているので、正規表現は「^.\\」になっている。ターゲットの一個のバックスラッシュのにマッチさせるために正規表現ではバックスラッシュを倍にしなければならないのは正規表現の問題だが、2番目と3番目のサンプルが示すように、文字列用にさらにバックスラッシュを加えなければならない原語もある。
    言語:perl コード:$f =~s/^.*\\//;
    言語:php コード:$f = preg_replace('/^.*\\\/','',$f);
    <中略…javaとvb.notという言語の正規表現が記載されている>
    "
    とあったので\をphpにおいてマッチさせるには、\\\が必要だと認識したのですが、どうも間違ってしまったのかもしれません。バックスラッシュは、phpの正規表現においてどのように表現するのでしょうか。

    キャンセル

  • 2017/11/29 20:15

    正規表現において \\ は "\" の文字を表しますが、\\\ と書いた場合は「"\" の文字」 と「不明な \」で構成されます。
    最後の \ はメタキャラクタとして成立しないので、コードに書き起こせば、文法エラーとなるはずです。
    下記はJavaScriptコードですが、SyntaxError となることが確認できます。
    /.*\\\/; // SyntaxError: Invalid regular expression: missing /

    キャンセル

  • 2017/12/04 19:27

    ご返答ありがとうございます。
    確かにjavascriptだと\\を合致させるのに必要なのは\\\や\\\\ではなく\\なのは、自身でも確認してみたので仰る通りであります。
    phpだと\\は、\\\、\\\\でないと合致できませんでした。(厳密にいうと置換だとワーニングのみだが、合致させるだけならワーニングが表示されつつ合致されている)
    //\をbに置換
    $test = preg_replace("/\\\\/","b","\\");
    $test1 = preg_replace("/\\\/","b","\\");//なぜ四つでも三つでも合致するのか...
    $test2 = preg_replace("/\\/","b","\\");
    $test3 = preg_replace("/\/","b","\\");
    print "置換(\が四つ):".$test;//b
    print "置換(\が三つ):".$test1;//b
    print "置換(\が二つ):".$test2;//Warning: preg_replace(): No ending delimiter '/' found in <略> on line <行>というエラーがでて何も置換されない
    print "置換(\が一つ):".$test3;//上記と同じエラー

    $test4 = preg_match("/\\\\/","\\",$hairetu);
    print "合致(\が四つ):".$hairetu[0];//合致
    $test5 = preg_match("/\\\/","\\",$hairetu);
    print "合致(\が三つ):".$hairetu[0];//合致
    $test6 = preg_match("/\\/","\\",$hairetu);
    print "合致(\が二つ):".$hairetu[0];//上記と同じエラーがでるが何故か合致する
    $test7 = preg_match("/\/","\\",$hairetu);
    print "合致(\が一つ):".$hairetu[0];//上記と同じエラーがでるが何故か合致する


    ということですが、やはりこれでも質問文の内容は成り立たないのでしょうか。

    キャンセル

  • 2017/12/04 23:51 編集

    To: aaaaaaaa さん
    親記事に追記しました。
    PHPの問題であれば、現象を再現可能なPHPのコードを書いた方が良かったと思います。
    質問文からは「正規表現の問題」としか読み取れなかったので、実際の問題から離れた内容で私は回答していました。

    キャンセル

  • 2017/12/05 19:28

    ご返答ありがとうございます。
    >>PHPの問題であれば、現象を再現可能なPHPのコードを書いた方が良かったと思います。
    ご迷惑をおかけして誠に申し訳ございません。仰る通りでした。

    ところで、重ね重ね申し訳ありませんが、phpのこの特有の仕様を加味したうえだと、質問文にある正規表現の動作は合っているのでしょうか。

    キャンセル

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

ただいまの回答率

91.35%

関連した質問

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

  • PHP

    15157questions

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

  • 正規表現

    568questions

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