• ベストアンサー

複雑な/による文字列の分割について

$str = "hello/$(hoge/$(hoge/good)/id)/namae"; このような文字列を/で以下のように分割して配列に入れようと考えています。 Array ( [0] => hello [1] => $(hoge/$(hoge/good)/id) [2] => namae ) しかし単にsplitで分割してもこのようにならないので正規表現でやりたいんですがどのようにしたらこのように分割できるでしょうか??

質問者が選んだベストアンサー

  • ベストアンサー
回答No.6

だいたいやりたいことが判りました。 ANo.5さんのと余り変わりませんが、サンプルです。 preg_replace_callbackを使っています。 function _get($path) { $ret = rand(1000, 9999); echo "path: $path[1] -> $ret\n"; return $ret; } function _kaiseki($str) { do { echo "str: $str\n"; $str = preg_replace_callback('|\$\(([^()\$]+)\)|', '_get', $str, -1, $cnt); } while ($cnt > 0); return $str; } $str = '$(DATA_ATR/$(DATA_ATR/$(DATA/hoge)/id)/NO)'; echo 'result: '. _kaiseki($str). "\n";

tadao1213
質問者

お礼

こういったやりかたもあるんですね。 ちょっと調べてみたいと思います。 何度もご回答していただきありがとうございます。

その他の回答 (5)

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.5

こんな感じでできないでしょうか? ###文字列を解析する関数 function _kaiseki($str){ $pattern = '/(^.*)(\$\([^\(\)]*\))(.*$)/'; for ($i = 0 ;;++$i) { //echo $str . "<br />"; preg_match($pattern,$str,$tmp); $replace_str = _get($tmp[2]); $replacement = '${1}' . $replace_str . '${3}'; $str = preg_replace($pattern,$replacement,$str); if (preg_match($pattern, $str) == "") break; } return $str; }

tadao1213
質問者

お礼

回答ありがとうございます。 これを参考に自分なりに修正してみたいと思います。

回答No.4

補足を拝見しましたが、いまいちよく判りませんでした。。。 直接的な回答ではありませんが、以下のような方法でプログラムからデータを取扱いしやすくする方法もあります。参考まで。 // '$(aaa/$(bbb/$(aaa/ccc)/id)/NO)' を以下に置換 // → 'array("aaa",array("bbb",array("aaa","ccc"),"id"),"NO")' // これをevalして、$hogeに代入します。 $str = '$(aaa/$(bbb/$(aaa/ccc)/id)/NO)'; $str = preg_replace(array('/\\b/', '/\\$/', '/\\//'), array('"', 'array', ','), $str); echo $str. "\n"; eval("\$hoge=$str;"); var_dump($hoge); evalを使うので、セキュリティ的な問題が無いように注意が必要ですが。

tadao1213
質問者

補足

もう少し補足します。全体的にはこんな流れになります。 $str="$(DATA_ATR/$(DATA_ATR/$(DATA/hoge)/id)/NO)"; echo _kaiseki($str); ###データを置換する関数 function _get($path){ if(preg_match('/^DATA/', $path)){ /*長いのでここは省略します。 解析したパスを渡してデータを取得する関数です。 (例えばidなどを取得します) */ }else if(preg_match('/^DATA_ATR/', $path)){ /*ここも長いので省略します。処理は上と同じ*/ } return $result; } ###文字列を解析する関数 function _kaiseki($str){ if(preg_match('/^\$/', $str)){ $str = preg_replace('/^\$/', "", $str); if(preg_match('/^\(([^$()]*)\)$/', $str, $tmp)){ $data = _get($tmp[1]); }else{ /*ここを通るときはこうなってます。 (1)DATA_ATR/$(DATA_ATR/$(DATA/hoge)/id)/NO 処理の流れはまず$(DATA/hoge)を_get()に渡してデータを得ます。 データを得るとこんな感じになるはずです。1111は取得したデータ。 (2)DATA_ATR/$(DATA_ATR/11111/id)/NO 次に$(DATA_ATR/11111/id)のデータを取得します。 また_get()を呼んで処理を行いデータを得ます。そうすると (3)DATA_ATR/12345/NO になるはずです。 最後にもう一度_get()を呼んで欲しかったデータを取得します。 */ } } return $data; } 悩んでいるのはこのパスの解析の部分です。よろしくお願いします。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.3

No.1です。 外してるかもしれませんが、こういうことでしょうか? whileでpreg_replace()をまわしてます。 (コメントアウトしているechoの//をはずせば途中経過が表示されます) $str="$(aaa/$(bbb/$(aaa/ccc)/id)/NO)"; $replace_str = Array("111","12345"); $pattern = '/(^.*)(\$\([^\(\)]*\))(.*$)/'; for ($i = 0 ;; ++$i) { //echo $str . "<br />"; $replacement = '${1}' . $replace_str[$i] . '${3}'; $str = preg_replace($pattern,$replacement,$str); if (preg_match($pattern, preg_replace($pattern,$replacement,$str)) == "") break; } echo $str;

回答No.2

$(xxx/yy/zzzzz)/aaa/$(bbb/$($(cc/ddd)/eee/fff)/ggg) のような文字列にも対処できるような汎用的なものにしたいんでしょうか? なおかつ、$()によるネストの回数に制限が無いとしたら、正規表現では太刀打ちできないと思います。 形式が決まっているのであれば、ANo1さんの方法などでできると思います。

tadao1213
質問者

補足

少し補足させてください。 実際に実装したいと考えているのは以下のような処理です。 $str=$(aaa/$(bbb/$(aaa/ccc)/id)/NO) $(aaa/ccc)のとき特定の数字(例えば111)を取得して $(aaa/$(bbb/111/id)/NO) となり、今度は$(bbb/111/id)のとき特定の数字(例えば12345)を取得します。 そして最後に$(aaa/12345/NO)となってこの文字列が指すあるデータを取得するという処理の流れになります。 このような処理をやりたいと考えていてこの文字列の解析に悩んでいるんです。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

$str = "hello/$(hoge/$(hoge/good)/id)/namae"; $replacement = '$1,$3,$5'; $pattern= '/(^[^\/]*)(\/)(\$.*)(\/)([^\/].*$)/'; $s = split(",",preg_replace($pattern,$replacement,$str)); でいけると思います。ただし、$strに","が入っていると誤動作します。

tadao1213
質問者

お礼

ありがとうございます。参考にしてみます。

関連するQ&A

専門家に質問してみよう