2011-05-02 85 views
2

我试图自己解决这个问题(甚至买了一本Kindle电子书!),但我正在努力解决php中的反向引用问题。rexexp for php的解决方案

我要的是像下面的例子:

var $html = "hello %world|/worldlink/% again"; 

output: 
hello <a href="/worldlink/">world</a> again 

我尝试这样的东西:

preg_replace('/%([a-z]+)|([a-z]+)%/', '<a href="\2">\1</a>', $html); 

,但没有喜悦。

有什么想法吗?我相信有人会发布确切的答案,但我也想请一个解释 - 以便我不必再问这些问题:)

+0

定义 “无欢”。你做了什么_exactly_,结果是什么_exactly_? – 2011-05-02 17:27:29

+1

我整理了一下你的问题。请花点时间去做一些小事,比如把'i's变成大写字母;对于那些花时间回答你的问题的人来说,这只是一个小小的礼貌。我还注意到,对于21个问题中的大部分问题都有良好的解决方案,但您只接受25%的答案。 – 2011-05-02 17:39:04

+0

关于您的第一条评论,我错误地认为任何经验丰富的正则表达式专家都可以尝试自己尝试。对不起,如果我错误地假设。关于你的第二条评论,我实际上对你的“纠正”态度感到不满。如果我亲自与俚语交谈,你会纠正我吗?此外,我看了一下其他问题,并禁止那些奇怪的问题,但实际的答案并不奏效 - 其中一些我实际上提到并要求提供更多帮助。我的问题很清晰,有礼貌,但为了您的利益,我已经在皇后英语中写下了这个问题。 – khany 2011-05-02 19:23:37

回答

0

下面是根据提供(使用非斜线分隔符,以避免逃逸斜线)的OP的数据/信息工作的版本:使用非斜线定界符

preg_replace('#%([a-z]+)\|([a-z/]+)%#', '<a href="\2">\1</a>', $html); 

,将减轻需要逃避斜线。

输出:

hello <a href="/worldlink/">world</a> again 

阐释

为什么你没有工作。首先,|是一个OR运算符,并且在您的示例中应该转义。其次,由于您使用的是/或预计会出现斜杠,因此最好使用非斜杠分隔符,如#。第三,斜线需要被添加到允许的匹配列表中。如前所述,您可能希望包含更多选项,因为任何类型的带数字的单词都会强调句点连字符会失败/中断脚本。希望这是你正在寻找的解释。

+0

这仅对所有URL的_very_严格子集“完全正确”。 – 2011-05-02 17:33:10

+0

修改了第一行以安抚挑剔的人。 @Tomalak,从技术上讲,事实上并非如此。但就主要文章中给出的例子和期望的结果而言,这是一个完全正确的版本。 OP没有声明他需要扩大范围,如果他的答案会是不同的。 – 2011-05-02 17:35:14

+0

@BradFJacobs:我想,这很清楚他想要做什么,那就是链接网址。我的回答并没有为他提供完整的解决方案,但它指出'([a-z /] +)'几乎不是URL匹配捕获;我想你的回答会更好,如果这样做的话。 – 2011-05-02 17:37:35

1

斜线“/”不包括在您允许的范围内[a-z] 。而是使用

preg_replace('/%([a-z]+)\|([a-z\/]+)%/', '<a href="\2">\1</a>', $html); 
+1

您还需要转义'|'和'/'。 – mellamokb 2011-05-02 17:26:08

+0

或者使用不同的分隔符,那么/会很好。 (如'#') – 2011-05-02 17:26:48

+0

并且可能希望扩大搜索范围,以防用户在路上稍后有类似“Page.HTML”的链接。 – mellamokb 2011-05-02 17:27:53

1

你的表达:

'/%([a-z]+)|([a-z]+)%/' 

只捕获一两件事。中间的|表示“或”。你试图捕获两者,所以你在那里不需要OR。你想要一个literal |符号所以你要逃避它:

'/%([a-z]+)\|([a-z\/]+)%/' 

/角色也需要纳入你的字符集,如上面逃脱。

+1

请原谅我的无知,这是什么RHS? – Erik 2011-05-02 17:31:23

+0

右侧。你[有点]现在修好了。 – 2011-05-02 17:33:43

0

这里对我来说是什么在起作用:

preg_replace('/%([a-z]+)\|([a-z\/]+)%/', '<a href="\2">\1</a>', $html); 
+0

是的,这工作谢谢你。并感谢所有在这个问题上的贡献者。 – khany 2011-05-02 19:37:57

1

您正则表达式(/%([a-z]+)|([a-z]+)%/)读这样:

比赛%其次+(=一个或 更多)a-z字符(和存储此 变成反向引用#1)。

或(所述|):

匹配+(=一个或多个)a-z 字符(和这个存储到 反向引用#2),接着是 %


你所寻找的是:

preg_replace('~%([a-z]+)[|]([a-z/]+)%~', '<a href="$2">$1</a>', $html); 

基本上我刚刚逃过|regex meta character(您可以通过与[]周围像我一样,或只是在前面加上一个向后斜线做到这一点\,我个人认为前者更易于阅读),并向第二个捕获组添加/

我也改变了你的delimiters/~因为波浪线是更不太可能出现在字符串中,如果你想使用/为您的分隔符,你也有逃避它们的出现在你的正则表达式来保持。

这也是您使用$语法,而不是\在您更换反向引用recommended

$replacement可能含有或(自PHP 4.0.4) $n引用的形式\\n的 ,后者形式是优选的一个。

+1

我喜欢使用'[|]'。 – 2011-05-02 17:40:12

+0

嗯。谢谢,但我得到这个'world again' so everything exvept the closing '' – khany 2011-05-02 19:34:04

+0

@ khany:我再次'你好world',并且我的正则表达式和你接受的答案没有什么大的区别,所以我的猜测是你误读了你的结果得到..? – 2011-05-02 22:16:13

0

您的正则表达式不会转义|,并且不包含URL的正确字符。

这是一个基本live例如仅支持A-Z和斜线:

preg_replace('/%([a-z]+)\|([a-z\/]+)%/', '<a href="\2">\1</a>', $html); 

在现实中,你会想那些[a-z]+块更改为更具表现力。做一些URL匹配正则表达式的搜索,并选择一个适合你想要的。