3

これは近いですが、連続する「属性」の一致に失敗しています:

$string = "single attribute [include file=\"bob.txt\"] multiple attributes [another prop=\"val\" attr=\"one\"] no attributes [tag] etc";
preg_match_all('/\[((\w+)((\s(\w+)="([^"]+)"))*)\]/', $string, $matches, PREG_SET_ORDER);
print '<pre>' . print_r($matches, TRUE) . '</pre>';

以下を返します。

Array
(
    [0] => Array
        (
            [0] => [include file="bob.txt"]
            [1] => include file="bob.txt"
            [2] => include
            [3] =>  file="bob.txt"
            [4] =>  file="bob.txt"
            [5] => file
            [6] => bob.txt
        )

    [1] => Array
        (
            [0] => [another prop="val" attr="one"]
            [1] => another prop="val" attr="one"
            [2] => another
            [3] =>  attr="one"
            [4] =>  attr="one"
            [5] => attr
            [6] => one
        )

    [2] => Array
        (
            [0] => [tag]
            [1] => tag
            [2] => tag
        )

)

[2] はタグ名、[5] は属性名、[6] は属性値です。

障害は 2 番目のノードにあります - キャッチしますが、キャッチattr="one"しませんprop="val"

ティア。

(これは限定された制御された使用のみを目的としており、広範な配布ではありません。したがって、一重引用符やエスケープされた二重引用符について心配する必要はありません)

4

1 に答える 1

1

残念ながら、そのようなキャプチャ グループを繰り返す方法はありません。個人的にはpreg_match、タグ自体を一致させるために使用します (つまり、正規表現内の余分な括弧をすべて削除します)。その後、foreach 一致で属性を抽出できます。このようなもの:

$string = "single attribute [include file=\"bob.txt\"] multiple attributes [another prop=\"val\" attr=\"one\"] no attributes [tag] etc";
preg_match_all('/\[\w+(?:\s\w+="[^"]+")*\]/', $string, $matches);
foreach($matches[0] as $m) {
    preg_match('/^\w+/', $m, $tagname); $tagname = $tagname[0];
    preg_match_all('/\s(\w+)="([^"]+)"/', $m, $attrs, PREG_SET_ORDER);
    // do something with $tagname and $attrs
}

タグを何らかのコンテンツに置き換えるpreg_replace_callback場合は、次のように使用する必要があることに注意してください。

$string = "single attribute [include file=\"bob.txt\"] multiple attributes [another prop=\"val\" attr=\"one\"] no attributes [tag] etc";
$output = preg_replace_callback('/\[\w+(?:\s\w+="[^"]+")*\]/', $string, function($match) {
    preg_match('/^\w+/', $m, $tagname); $tagname = $tagname[0];
    preg_match_all('/\s(\w+)="([^"]+)"/', $m, $attrs, PREG_SET_ORDER);
    $result = // do something with $tagname and $attrs
    return $result;
});
于 2013-03-19T04:49:21.607 に答える