2

次のパターンの文字列を解析するためのphpの正規表現を探しています。コマンドは、次のように二重角括弧で囲まれています。

[[a src="" desc=""]]

ここで、a、src、descはキーワードです(変更されません)。srcを指定する必要がありますが、descはオプションです。srcまたはdescの値は、二重引用符または一重引用符で囲むことができます。また、srcとdescは任意の順序で指定できます。たとえば、次のパターンはすべて有効です

[[a src="http://a.c.d" desc ="hello"]]
[[a src   ="http://a.c.d" desc= 'hello']]
[[a desc ="hello " src=  'http://a.c.d' ]]
[[a src = "http://a.c.d" ]]
[[a    src="http://a.c.d" desc ="hello"]]

値と「a」、「src」、「desc」、「=」(引用符なし)の間のスペースはすべて無視する必要があります。このコマンドを次のようなhtmlタグに置き換えます

SOMETHING_EXTRACT_FROM_DESC

作業を行うために1つの正規表現を考えるのはかなり難しいようです。これで、異なるケースを個別に処理するための3つの正規表現セットアップができました。こんな感じ

$pattern = '/\[\[a[:blank:]+src[:blank:]*=[:blank:]*"(.*?)"[:blank:]+desc[:blank:]*=[:blank:]+"(.*?)"\]\]/i';
$rtn = preg_replace($pattern, '<a href="${1}">${2}</a>', $src);

$pattern = '/\[\[a[:blank:]+desc[:blank:]*=[:blank:]*"(.*?)"[:blank:]+src[:blank:]*=[:blank:]+"(.*?)"\]\]/i';
$rtn = preg_replace($pattern, '<a href="${1}">${2}</a>', $rtn);

$pattern = '/\[\[a[:blank:]+src[:blank:]*=[:blank:]+"(.*?)"\]\]/i';
$rtn = preg_replace($pattern, '<a href="${1}">${2}</a>', $rtn);

しかし、これは機能しません。正規表現を学ぶのは難しいです:(

4

1 に答える 1

1

私はあなたが要求したすべてに一致する正規表現を書きましたが、最後に説明する少しのオーバーヘッドを許容します。しかし、最初に正規表現:

このように見えます:

\[\[a(\s+(src|desc)\s*=\s*('[^']*'|"[^"]*")){1,2}\s*\]\]

あなたがそれを理解できるように私はそれをブレーキします:

  • \[\[ ... \]\]一致[[ ... ]]、開始と終了
  • \s任意の空白(スペースとタブ)に一致\s+し、少なくとも1つを必要とします
  • (src|desc)src文字列または文字列のいずれかに一致しますdescこれはOR演算子です。ORに一致します。srcdesc
  • '[^']*'は2つの一重引用符に一致し、その間のものは一重引用符ではありません
  • "[^"]*"二重引用符と同じ
  • ('[^']*'|"[^"]*")上記の2つのいずれかに一致します
  • (src|desc)\s*=\s*('[^']*'|"[^"]*")次のようなトークンに一致しますsrc='something'
  • {1,2}上記の式に追加して、1回または2回何かに一致し、それらのトークンの1つまたは2つをメッシュします

そして、それはほとんどそれです。唯一の問題は、これにも一致することです。

[[a src="http://a.c.d" src="http://a.c.d"]]

これはミスマッチだと思います。気にならない場合は、行ってもかまいません。それ以外の場合は、ors(つまり:)で大きなアトムを使用するという概念全体を変更し|、別のアプローチを取る必要があります。たとえば、先読みを使用できます。しかし、それはかなり速く本当に厄介になります。

ここでオンラインでテストできます

バックスラッシュと\sのものを削除すると、正規表現がはるかに読みやすくなります。これは機能しませんが、理解するのに役立つと思います。

[[a ( (src|desc)=('[^']*'|"[^"]*") ){1,2} ]]
于 2013-01-24T06:34:01.920 に答える