1

ユーザーが入力したタグを実際の html タグに置き換える JavaScript RegEx を作成しようとしてい[b]ます<b>。私が使用している正規表現はそのように見えます

var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;

次の JavaScript で

s.replace(exptags,"<$1>$2</$1>");

これは、単一のネストされたタグでうまく機能します。たとえば、次のようになります。

[b]hello[/b] [u]world[/u]

ただし、タグが互いにネストされている場合は、外側のタグのみに一致します。たとえば、

[b]foo [u]to the[/u] bar[/b]

bこれはタグのみに一致します。どうすればこれを修正できますか? 開始文字列が結果と同じになるまでループする必要がありますか? ((.){1,}?)パターンも間違っているような気がしますか?

ありがとう

4

8 に答える 8

3

最も簡単な解決策は、タグが閉じているかどうかに関係なく、すべてのタグを置き換えて、.innerHTMLそれらが一致しているかどうかを確認することです。その方がはるかに弾力性があります..

var tagreg = /\[(\/?)(b|u|i|s|center|code)]/ig
div.innerHTML="[b][i]helloworld[/b]".replace(tagreg, "<$1$2>") //no closing i
//div.inerHTML=="<b><i>helloworld</i></b>"
于 2008-09-17T13:51:36.877 に答える
1

知る限り、正規表現で再帰を表現することはできません。

ただし、バランスの取れた一致を使用して、.NET の System.Text.RegularExpressions でそれを行うことができます。詳細はこちら: http://blogs.msdn.com/bclteam/archive/2005/03/15/396452.aspx

.NET を使用している場合は、おそらくコールバックで必要なものを実装できます。そうでない場合は、独自の小さな JavaScript パーサーを作成する必要があります。

繰り返しになりますが、サーバーにヒットする余裕がある場合は、完全なパーサーを使用できます。:)

とにかく、これは何のために必要ですか?プレビュー以外の場合は、サーバー側で処理することを強くお勧めします。

于 2008-09-17T08:18:53.993 に答える
0

一致しなくなるまで、正規表現を繰り返し適用することができます。それは "[b][b]foo[/b][/b]" => "<b>[b]foo</b>[/b]" => "<b><b >foo</b></b>" ですが、私が見る限り、最終結果は一致する (必ずしも適切にネストされているとは限りませんが) タグを持つ適切な文字列です。

または、「正しく」実行したい場合は、単純な再帰降下パーサーを記述してください。「[b]foo[u]bar[/b]baz[/u]」が機能することを期待する人もいるかもしれませんが、これをパーサーで認識するのは困難です。

于 2008-09-17T09:16:33.793 に答える
0

どうですか:

tagreg=/\[(.?)?(b|u|i|s|center|code)\]/gi;
"[b][i]helloworld[/i][/b]".replace(tagreg, "<$1$2>");
"[b]helloworld[/b]".replace(tagreg, "<$1$2>");

私にとって、上記は以下を生成します:

<b><i>helloworld</i></b>
<b>helloworld</b>

これはあなたが望むことをしているように見え、単一のパスしか必要としないという利点があります。

免責事項: 私は JS でコーディングすることはあまりないので、間違いがあれば遠慮なく指摘してください :-)

于 2008-09-17T13:11:35.383 に答える
0

内側の型紙が面倒なのはその通りです。

((.){1,}?)

つまり、少なくとも 1 回はキャプチャー マッチを実行し、その後全体をキャプチャーします。タグ内のすべての文字がグループとしてキャプチャされます。

また、必要のないときに終了要素名をキャプチャしており{1}、それが暗示されているときに使用しています。以下は、クリーンアップ バージョンです。

/\[(b|u|i|s|center|code)](.+?)\[\/\1]/ig

他の問題についてはわかりません。

于 2008-09-17T08:31:21.203 に答える
0

はい、ループする必要があります。あるいは、タグは HTML タグに非常によく似ているため、個別に置き換えること[b]<b>できます[/b]</b>(.){1,}? (.*?) と同じです - つまり、任意のシンボル、可能な限り最小のシーケンス長です。

更新: MrP のおかげで、(.){1,}? は (.)+? です。

于 2008-09-17T08:27:24.770 に答える
0

ネストされたブロックが置き換えられない理由は、[b] の一致が [/b] の後に位置を配置するためです。したがって、 ((.){1,}?) に一致するものはすべて無視されます。

サーバー側で再帰的なパーサーを書くことは可能です -- Perl はqr//を使用し、Ruby はおそらく似たようなものを持っています。

ただし、必ずしも真の再帰が必要なわけではありません。比較的単純なループを使用して、文字列を同等に処理できます。

var s = '[b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]';
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;

while (s.match(exptags)) {
   s = s.replace(exptags, "<$1>$2</$1>");
}

document.writeln('<div>' + s + '</div>'); // after

この場合、2 つのパスを作成します。

0: [b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]
1: <b>hello</b> <u>world</u> <b>foo [u]to the[/u] bar</b>
2: <b>hello</b> <u>world</u> <b>foo <u>to the</u> bar</b>

また、正規表現をクリーンアップするためのいくつかの提案:

var exptags = /\[(b|u|i|s|center|code)\](.+?)\[\/(\1)\]/ig;
  • {1} は、他のカウント指定子が存在しない場合に想定されます
  • {1,} は + に短縮できます
于 2008-09-17T09:19:57.217 に答える
0

Richard Szalay に同意しますが、彼の正規表現は正しく引用されませんでした。

var exptags = /\[(b|u|i|s|center|code)](.*)\[\/\1]/ig;

よりきれいです。にも変更.+?することに注意してください.*。には 2 つの問題があります.+?

  1. [u][/u] の間には少なくとも 1 文字 (+) がないため、一致しません。
  2. 貪欲でない一致は、それ自体の中にネストされた同じタグをうまく処理しません (?)
于 2008-09-17T09:51:31.433 に答える