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

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

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

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

正規表現

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

Q&A

1回答

250閲覧

末尾に来た後の動作は、

aaaaaaaa

総合スコア501

PHP

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

正規表現

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

0グッド

0クリップ

投稿2017/11/28 10:26

編集2022/01/12 10:55

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

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

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

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

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

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

か、

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

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

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

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

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

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

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

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

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

guest

回答1

0

バックトラック

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

JavaScript

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

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

PHPの文字列構文

PHP

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

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

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

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

PHP

1echo "/\\/\n"; 2echo preg_replace("/\\/","b","\")."\n"; 3echo "/\/\n"; 4echo preg_replace("/\/","b","\")."\n";

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

Re: aaaaaaaa さん

投稿2017/11/28 23:44

編集2017/12/04 14:48
think49

総合スコア18156

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

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

aaaaaaaa

2017/11/29 09:33

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

2017/11/29 09:56

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

2017/11/29 10: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の正規表現においてどのように表現するのでしょうか。
think49

2017/11/29 11:15

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

2017/12/04 10: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];//上記と同じエラーがでるが何故か合致する ということですが、やはりこれでも質問文の内容は成り立たないのでしょうか。
think49

2017/12/04 14:51 編集

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

2017/12/05 10:28

ご返答ありがとうございます。 >>PHPの問題であれば、現象を再現可能なPHPのコードを書いた方が良かったと思います。 ご迷惑をおかけして誠に申し訳ございません。仰る通りでした。 ところで、重ね重ね申し訳ありませんが、phpのこの特有の仕様を加味したうえだと、質問文にある正規表現の動作は合っているのでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問