1

私はこのようなテキストをいくつか持っています、それはカスタムのマークダウンスタイルのフォーマットで書かれています。例えば:

[Lorem ipsum] 
Dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 

[Ut wisi] 
[Enim ad minim veniam](a), quis nostrud exerci tation ullamcorper. 
suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat. 
Vel illum dolore eu feugiat nulla facilisis at vero.
[Ros et accumsan et iusto odio dignissim](b) qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. 

[[Nam liber]](c)
Tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.

ご覧のとおり、見出しを囲む角かっこがあり、角かっこに続いて、正規表現と一致させようとしている文字を含む括弧があります。私が使用しようとしている正規表現は次のとおりです。

preg_match_all("#\[(.*?)\]\(([a-z]+)\)#is",$html,$matches)

この^の問題は、[Lorem ipsum]から(a)の終わりまで一致することです。

次のものを使用することもできますが、これが正しく機能しないように、角かっこで見出しを含めることができる必要があります。

preg_match_all("#\[([^]]+)\]\(([a-z]+)\)#is",$html,$matches)

少し読んだ後、私が必要としているのは先読みだと思いますが、頭を動かすことができませんでした。どんな助けでも大歓迎です。


明確化

私は基本的に、テキストの一部を角かっことかっこで囲み、既存の角かっこが競合を引き起こすことなく正規表現と一致させることができるようにしたいと考えています。テキストの例:

[[Lorem ipsum]](a)
Dolor sit amet, [consectetuer adipiscing elit](b), sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 

希望する一致:

[[Lorem ipsum]](a)
[consectetuer adipiscing elit](b)

または...もっと複雑

[[Lorem ipsum]
Dolor sit amet, sed diam nonummy nibh euismod](a) tincidunt ut laoreet dolore magna aliquam erat volutpat. 

希望する一致:

[[Lorem ipsum]
Dolor sit amet, sed diam nonummy nibh euismod](a)

出来ますか?

4

3 に答える 3

4

どうぞ。

preg_match_all("~
    \[(              # open outer square brackets and capturing group
    (?:              # open subpattern for optional inner square brackets
        [^[\]]*      # non-square-bracket characters
        \[           # open inner square bracket
        [^[\]]*      # non-square-bracket characters
        ]            # close inner square bracket
    )*               # end subpattern and repeat it 0 or more times
    [^[\]]*          # non-square-bracket characters
    )]               # end capturing group and outer square brackets
    (?:              # open subpattern for optional parentheses
        \((          # open parentheses and capturing group
        [a-z]+       # letters
        )\)          # close capturing group and parentheses
    )?               # end subpattern and make it optional
    ~isx",
    $input,
    $matches);

そして、1行の正規表現:

"~\[((?:[^[\]]*\[[^[\]]*])*[^[\]]*)](?:\(([a-z]+)\))?~isx"

作業デモ

于 2012-11-08T23:55:41.803 に答える
1

m.buettnerの答えは素晴らしいです。それは正確であり、十分に文書化されています(それは私の賛成票を得て、選択された答えのままでいるに値します)。正規表現がフリースペースモードで自己文書化されているという事実が本当に気に入っています。ただし、完全を期すために(そして別のコメントスタイルのデモンストレーションとして)、これは同等の(ただし少し効率的な)正規表現ソリューションです。

preg_match_all('/
    # Match a "[...[...]...[...]...](...)" structure.
    \[               # Literal open square bracket.
    (                # $1: Square bracket contents.
      [^[\]]*        # {normal*} Zero or more non-[].
      (?:            # Begin {(special normal*)*}.
        \[[^[\]]*\]  # {special} Nested matching [] pair.
        [^[\]]*      # More {normal*} Zero or more non-[].
      )*             # End {(special normal*)*}.
    )                # $1: Square bracket contents.
    \]               # Literal close square bracket.
    (?:              # Optional matching parentheses.
      \(             # Literal open parentheses.
      ([A-Za-z]+)    # $2: Parentheses contents.
      \)             # Literal close parentheses.
    )?               # Optional matching parentheses.
    /x',
    $input,
    $matches);

改善点(主に化粧品/文体):

  • 'single quotes'正規表現はではなくで囲まれています"double quotes"。PHPでは、二重引用符で囲まれた文字列を使用した解釈のレベルが高くなり、処理する文字エスケープシーケンスがさらに多くなります("$"特に文字はいたずらを引き起こす可能性があります)。結論:PHPでは、正規表現パターンを一重引用符で囲まれた文字列で囲むのが最善です(つまり、バックスラッシュのスープが少なくなります)。
  • に一致する式ロジックは、Friedlの「Unrolling-the-Loop」効率手法[nested [square bracket] structure]を実装するために再配置されました。これにより、外側の角かっこに入れ子になった角かっこがない場合のバックトラックが少なくなります。
  • キャプチャグループの開き括弧と閉じ括弧(複数の行にまたがる)は、視覚的な一致を容易にするために同じレベルにインデントされます(つまり、垂直方向に整列されます)。
  • キャプチャグループ番号は、開き括弧と閉じ括弧のある行のコメントに含まれています。
  • s 単一行修飾子が削除されます(必要ありません-ドットはありません!)。
  • i 大文字と小文字を区別しない修飾子が削除され、影響を受ける文字クラスが補正するよう[a-z]に変更されました。[A-Za-z](一部の正規表現エンジンは、大文字と小文字を区別するモードの場合、少し速く実行されます。)
  • 文字通りの"]"閉じ角括弧メタ文字は明示的にエスケープされます。つまり、次のようになります"\]"。(これは必須ではありませんが、私見の良い習慣です)。
  • キャプチャグループ$2は1行に統合されます。
  • 正規表現の全体的な目的を説明する全幅のヘッダーコメントが正規表現の上部に追加されます。
于 2012-11-09T04:30:18.763 に答える
0

最初の正規表現を少し調整する必要があると思います。

preg_match_all("#\[(.*?)\](?:\(([a-z]+)\))?#is",$html,$matches)
                          ^^^            ^^

このように、括弧で囲まれた文字はオプションです。

編集:

説明を踏まえて、新しい正規表現を次に示します。

\[((?:[^][]|\[[^][]*?\])*?\](?:\(([a-z]+)\))?

これがRubularのデモです。

于 2012-11-08T23:18:31.020 に答える