2009-12-08 60 views
2
替换使用正则表达式和反向引用串

我试图从HTML转换成乳胶,并想改变这一点:Clojure中

<a href="www.foo.com/bar">baz</a> 

到:

baz\footnote{www.foo.com/bar} 

我想生成一个Clojure函数来获取大量文本,并替换给定段落中存在的匹配项。

我已经试过

(.replaceAll 
    "<a href=\"foo.com\">baz</a>" 
    "<a.*href=\"(.*)\">(.*)</a>" 
    "\2\\footnote{\1}") 

但返回:

"^Bfootnote{^A}" 

我也看了clojure.contrib.str-utils2,其中有一个替换使用正则表达式的功能,但它似乎没有处理反向引用。我错过了什么吗?这是错误的方式吗?任何帮助表示赞赏。

+0

关于在下面的答案中提到的正则表达式和HTML的不幸选择,我反驳说这是一次性程序,而源是东西是以前由我编程生成。我认为一个XML解决方案将是可持续性和可重用性的正确途径,但在这一点上,我只是试图一起破解它。 – 2009-12-08 13:27:26

回答

4

You should not parse HTML with a regex...

两件事情:

  1. Java使用$1$2指捕捉组,不\1\2

  2. 在替换文本中需要更多反斜杠。 Clojure阅读器消耗了第一级反斜杠,因为它是一个字符串。正则表达式消耗了第二级反斜杠。不幸的是,Clojure没有“原始”字符串文字的一般语法(还没有?)。 Clojure文字正则表达式的语法#""会为您节省一些反斜杠,但是普通的字符串没有那种魔力。

所以:

user> (.replaceAll "<a href=\"www.foo.com/bar\">baz</a>" 
        "<a.*href=\"(.*)\">(.*)</a>" 
        "$2\\\\footnote{$1}") 
"baz\\footnote{www.foo.com/bar}" 

你也可以这样来做:

user> (require '(clojure.contrib [str-utils2 :as s])) 
nil 
user> (s/replace "<a href=\"www.foo.com/bar\">baz</a>" 
       #"<a.*href=\"(.*)\">(.*)</a>" 
       (fn [[_ url txt]] 
        (str txt "\\\\footnote{" url "}"))) 
"baz\\footnote{www.foo.com/bar}" 

"\2"是控制字符(ASCII字符2),这就是为什么它显示为^B。与做(char 2)几乎相同。

+0

是否有理由通过s/replace选项选择.replaceAll,反之亦然?看起来他们都应该工作,但是有更高的处理需求,还是更常用的Clojure? 给定相同的功能,最佳实践是什么? – 2009-12-08 13:30:08

+0

'clojure.contrib.str-utils2/replace'可以做更多的事情(你可以传入一个fn作为第三个参数)。但它是您项目的附加依赖项。它们都是惯用的,你不必回避Java调用。我个人使用'str-utils'来处理大多数事情。 – 2009-12-08 17:52:12

1

如果你想真的很漂亮,你可以去clojure.xml。它会返回一个可以随意修改的结构树。你上面的例子是这样的:

{:tag :a :attrs {:href "www.foo.com/bar"} :content ["bar"]}

这可以很容易地转换为类似:

["bar" {:footnote "www.foo.com/bar"}]

可以很容易地连载回你所希望的形式。最好的部分是:没有不可维护的正则表达式。 :) YMMV当然.....