使用JavaScript的正则表达式:用某些东西替换特定的子匹配组

时间:2012-07-09 22:18:12

标签: javascript html regex

这是我的情况。我想识别Markdown的一个链接(在这种情况下,只有一种特殊的链接方式很好,就是这种格式:[link text](url "optional title"),而我正在尝试做的是将这个Markdown文本放入{{1}标记带有适当包装在<pre>标记中的网址。

假例:

转换

<a>

[link text](url "optional title")

所以我挖出了Markdown解析器使用的正则表达式:

[link text](<a href='url'>url</a> "optional title")

好评的细分有助于了解发生了什么,显然我需要做的就是用/* text = text.replace(/ ( // wrap whole match in $1 \[ ( (?: \[[^\]]*\] // allow brackets nested one level | [^\[\]] // or anything else )* ) \] \( // literal paren [ \t]* () // no id, so leave $3 empty <?( // href = $4 (?: \([^)]*\) // allow one level of (correctly nested) parens (think MSDN) | [^()\s] )*? )>? [ \t]* ( // $5 (['"]) // quote char = $6 (.*?) // Title = $7 \6 // matching quote [ \t]* // ignore any spaces/tabs between closing quote and ) )? // title is optional \) ) /g, writeAnchorTag); */ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?((?:\([^)]*\)|[^()\s])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag); 替换$4子匹配。

但当然我不能只做<a href='$4'>$4</a>,因为这会用普通链接取代我的整个Markdown链接标记(包括链接文本和可选标题)。我希望普通链接显示在原始Markdown中,这样它仍然看起来就像str.replace(re,"<a href='$4'>$4</a>");中的原始Markdown(但现在有一个可点击的链接)。

所以,让我们看看......

提取<pre>

$4

在这里,我被卡住了,因为我想坚持var group_4 = str.replace(re, "$4"); // Does anybody know a more efficient way to do this? I'm not trying to replace I just need to get the 4th group 作为"<a href='"+group_4+"'>"+group_4+"</a>"的替代品。

有人给我提示吗?我很确定这可以做到,我怀疑它也可以优雅地完成。

我已经找到了一个可能的解决方案(这是错误的),即删除正则表达式组$4之外的部分。我不认为这是足够的,因为它没有根据链接内容进行任何实际的链接检测(即你可以使用根本不是真正链接的东西来定义Markdown链接)。所以我应该使用原始正则表达式,以确保我转换为$4的内容实际上是(Markdown内联样式)链接的一部分。

1 个答案:

答案 0 :(得分:0)

我想我有办法用我已经知道的方法来解决这个问题。只需更换原装零件即可。这意味着必须有其他子匹配覆盖$4之前和之后的整个表达式。假设有一个组$x包含从最开始到$4的匹配和另一个组$y,其中包含从$4结尾到结尾的匹配字符串,我所要做的就是str.replace(re,"$x<a href='$4'>$4</a>$y")并完成它。

现在,看看是否有可能修改我们的正则表达式,以便在向我提供这些组时不更改其接受的语言。

更新:再看一下它实际上非常基本:

str.replace(re,"[$2]($4 $5)")

让我99%的方式完全复制原始输入,唯一不合适的部分是$4$5之间的空格,输入中{{1}所以我要做的就是将它包装到原始正则表达式中的新组中。我相信它会变成[ \t]*所以它会成为:

$5

下面一行中的克拉表示添加了parens的位置。

/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?((?:\([^)]*\)|[^()\s])*?)>?([ \t]*)((['"])(.*?)\6[ \t]*)?\))/g
                                                                      ^      ^

应该产生完全原始的,所以

str.replace(re,"[$2]($4$5$6)")

应该这样做。

现在剩下的就是设计一种只在这些链接构造之外转义HTML的方法,因为我不想转义锚标记。嗯。