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

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

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

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

正規表現

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

Q&A

解決済

2回答

6533閲覧

正規表現でディレクトリパスをパースしたい

BECK_

総合スコア94

PHP

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

正規表現

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

0グッド

0クリップ

投稿2017/02/06 13:13

編集2017/02/06 13:31

PHPのpreg_match関数でディレクトリパスをパースしたいのですが、/の分割で上手くパースしてくれません。

/aaaa/bbbb/ccc/を各ディレクトリ名を取り出したく、パターン'#^/(.+?)/(.+?)/(.+?)/$#' で最短マッチさせた場合、
期待通りの結果を得られます。

$sts = preg_match('#^/(.+?)/(.+?)/(.+?)/$#', '/aaaa/bbbb/ccc/', $matches);
if($sts) var_dump($matches);

結果)
array(4) {
[0]=>
string(15) "/aaaa/bbbb/ccc/"
[1]=>
string(4) "aaaa"
[2]=>
string(4) "bbbb"
[3]=>
string(3) "ccc"
}

ですが、どうしても'#^/(.+?)/(.+?)/$#'のパターンでもマッチしてしまいます。

$sts = preg_match('#^/(.+?)/(.+?)/$#', '/aaaa/bbbb/ccc/', $matches);
if($sts) var_dump($matches);

結果)
array(3) {
[0]=>
string(15) "/aaaa/bbbb/ccc/"
[1]=>
string(4) "aaaa"
[2]=>
string(8) "bbbb/ccc"
}

bbbb/cccが最短マッチが効いていない感じがしますが、この場合どの様なパターンを記述すれば良いのでしょか?
宜しくお願いします。

*explode関数ではなく、今回は正規表現にて実現したく考えております。

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

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

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

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

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

ikedas

2017/02/06 13:16

正規表現でないとだめでしょうか。
BECK_

2017/02/06 13:39

はい。本文に記載してますがexplode関数等では簡単に実現できますが正規表現で実現が必要です。それと最短マッチが失敗している根本的な原因も知りたいと思います。
guest

回答2

0

ベストアンサー

どうしても切り分けたいなら一番単純なのは[^/]をマッチさせること

$str="/aaaa/bbbb/ccc/"; $pattern="#^/([^/]+)/([^/]+)/([^/]+)/$#"; preg_match($pattern,$str,$m); print_r($m);

これなら$pattern="#^/([^/]+)/([^/]+)/$#";
にはマッチしません。

追記

そもそも正規表現を使うのはどちらが目的でしょうか?

  • パターンマッチさせて合致しないものをはじく
  • パターンマッチさせて合致したものだけ抽出する

それによって使う正規表現もかわってきます。
たとえばもしスラッシュに囲まれた文字列を抽出したいというだけなら
以下のような書き方をするほうが楽です

$str="/aaaa/bbbb/ccc/"; $pattern="#(?<=/).+?(?=/)#"; preg_match_all($pattern,$str,$m); print_r($m);

投稿2017/02/06 13:43

編集2017/02/07 01:46
yambejp

総合スコア114572

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

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

BECK_

2017/02/07 01:34

yambejpさん回答ありがとう御座います。 例で掲載頂いた通り/以外で抽出すれば期待通りの動作をします。 さしあたりこれで問題ないのですが、PCREのアルゴリズム的に今回の様なケースをカバーする事は出来ないのかと思い少し深掘りしています。(単純なケースだと思いますので) 引き続き「このパターンがダメじゃん!」とかこれならおk的な回答があれば勉強になります。
yambejp

2017/02/07 01:48

追記しておきました PCREの特徴を理解しながらうまく使ってください
BECK_

2017/02/07 02:00

ご丁寧に有り難う御座います。 簡単な実装で逃げたくなくちゃんと理解したいと思いながら皆様を巻き込んでますw 勉強になります。 少しずつ整理しながら考えてみます。
guest

0

最短マッチの意味を誤解しています。
マッチする中で最短です。マッチするかどうかは別の話です。
やや不正確な表現ですが、「マッチしない最短」と「マッチする最長」があればマッチするほうが採用されます。

yambejpさんの回答にあるように、[^/]を使ってください。

投稿2017/02/07 01:32

otn

総合スコア84421

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

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

BECK_

2017/02/07 01:57

otnさん、ありがとう御座います。 >やや不正確な表現ですが、「マッチしない最短」と「マッチする最長」があれば >マッチするほうが採用されます。 いささか難しいですね.. /aaaa/bbbb/ccc/で、2番目の抽出結果が bbbb/ccc となってますが、bとcの間の/はマッチしていると考えてましたので、パターンは評価されないと思ってました。 改めて勉強し直します。
otn

2017/02/07 02:06

すでにマッチした1番目の括弧分を取り除くと、"/bbb/ccc/"に対して#^/(.+?)/$#をマッチさせることになりますが、これは括弧内が bbb/ccc にマッチして成功します。 という簡単なことだと思います。 行末指定の無い、#^/(.+?)/# なら bbb にマッチですが。
BECK_

2017/02/07 02:21

>行末指定の無い、#^/(.+?)/# なら bbb にマッチですが。 なるほど、理解出来ました! /にマッチしていた訳ではなく、/$にマッチしていた訳ですね〜(汗 冷静に考えればごもっともです。 時間のない急場での正規表現は思い込みによる勘違いを誘発しますね(僕の場合ですがw) 修行しなければw ありがとう御座います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問