0

json に似た大規模な多次元構造で構造化されたファイルがありますが、json ライブラリを使用するには十分ではありません。

データは次のようになります。

alpha {
    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;
}

私が構築しようとしている正規表現 (preg_match_all の場合) は、データを表す多次元の PHP 配列を構築して、一致を再帰できるように、各最上位の親 ({} 波括弧で区切られている) と一致する必要があります。

私が試した最初の正規表現は/(?<=\{).*(?=\})/s、中括弧内のコンテンツを貪欲に一致させるものですが、最上位レベルに複数の兄弟がいる場合、一致が貪欲すぎるため、これは正しくありません。以下の例:

正規表現/(?<=\{).*(?=\})/s一致の使用は次のように与えられます。

マッチ 1:

    beta {
        charlie;
    }
    delta;
}

echo;
foxtrot {
    golf;
    hotel;

代わりに、結果は次のようになります: 一致 1:

    beta {
        charlie;
    }
    delta;

マッチ 2:

    golf;
    hotel;

正規表現ウィザード、ここで欠落している機能は何ですか、またはphpでこれを解決する必要がありますか? どんなヒントでも大歓迎です:)

4

3 に答える 3

2

これを正規表現で行うことはできません

または、深いブロックと浅いブロックを一致させたい場合は、 and を使用\{[^\{\}]*?\}preg_replace_callback()て値を保存し、 returnnullして文字列から消去することができます。コールバックは、それに応じて値をネストする必要があります。

$heirarchalStorage = ...;
do {
    $string = \preg_replace_callback('#\{[^\{\}]*?\}#', function($block)
    use(&$heirarchalStorage) {
        // do your magic with $heirarchalStorage
        // in here
        return null;
    }, $string);
} while (!empty($string));

不完全、未テスト、無保証。

このアプローチでは、文字列もラップする必要があります{}。そうしないと、最終的な一致が発生せず、永遠にループします。

これは非常に多くの (非効率的な) 作業であり、JSON などのよく知られた交換/ストレージ形式で簡単に解決できます。

1できますが… 」と書きたかったのですが、「できません」ともう一度言います2

2しない

于 2012-07-13T09:42:08.527 に答える
2

もちろん、正規表現でこれを行うことができます。

preg_match_all(
    '/([^\s]+)\s*{((?:[^{}]*|(?R))*)}/',
    $yourStuff,
    $matches,
    PREG_SET_ORDER
);

これにより、マッチで次のことが得られます。

[1]=>
string(5) "alpha"
[2]=>
string(46) "
beta {
    charlie;
}
delta;
"

[1]=>
string(7) "foxtrot"
[2]=>
string(22) "
golf;
hotel;
"

少し分解します。

([^\s]+)                # non-whitespace (block name)
\s*                     # whitespace (between name and block)
{                       # literal brace
    (                   # begin capture
        (?:             # don't create another capture set
            [^{}]*      # everything not a brace
            |(?R)       # OR recurse
        )*              # none or more times
    )                   # end capture
}                       # literal brace

参考までに、これは深さ n レベルのブレースでうまく機能します。

于 2012-07-13T10:12:47.493 に答える
0

とをpreg_split一致させることで何かを得ることができると思います。結果を調べることで、配列を構築することができます。開始タグに一致すると深くなり、終了タグに一致すると上に行く再帰関数を使用します。[a-zA-Z0-9][:blank]+{}

それ以外の場合、最もクリーンな解決策はANTLR文法を実装することです!

于 2012-07-13T09:42:59.990 に答える