为什么我的正则表达式不匹配字符串的结尾?

时间:2013-09-18 17:29:48

标签: ruby regex gsub

我正在尝试将<p>标记添加到用户生成的文本中,而不是换行符。

这是我的代码:

string.gsub(/(.*)[\n\r\Z$]+/, "<p>\\1</p>")

替换完全按照第一段的预期工作,但如果我添加额外的回车,它只包装最后的文本块。似乎\Z$与我期望的不匹配。

我做错了什么?

此:

Lorem ipsum dolor sit amet. 
\n
Vestibulum laoreet erat id quam.

变成这样:

<p>Lorem ipsum dolor sit amet.</p> 

Vestibulum laoreet erat id quam.

但是这个:

Lorem ipsum dolor sit amet. 
\n
Vestibulum laoreet erat id quam.
\n

变成这样:

<p>Lorem ipsum dolor sit amet.</p> 

<p>Vestibulum laoreet erat id quam.</p>

2 个答案:

答案 0 :(得分:1)

尝试使用正则表达式

/\A((?:.|[\n\r])+)\Z/

并替换为\\1

您当前的正则表达式与输入字符串中的最后一个换行符/托架字符匹配,\Z甚至无效。 $是字符类中的文字字符。


如果您的意思是想要在<p></p>之间换行,那么您只需使用:

/^(.+)$/

并替换为\\1

或者使用正则表达式:

/([^\n\r]+)/

答案 1 :(得分:1)

我会这样做:

ary = [
  "Lorem ipsum dolor sit amet.\nVestibulum laoreet erat id quam.",
  "Lorem ipsum dolor sit amet.\nVestibulum laoreet erat id quam.\n"
]

puts ary.map{ |a| 
  a.scan(/.+$/).map{ |s| "<p>#{s}</p>" } 
}
# >> <p>Lorem ipsum dolor sit amet.</p>
# >> <p>Vestibulum laoreet erat id quam.</p>
# >> <p>Lorem ipsum dolor sit amet.</p>
# >> <p>Vestibulum laoreet erat id quam.</p>

两个字符串都以相同的方式返回。

正则表达式不是魔术棒,你可以挥手解决每个问题。他们有自己的用途,但是有太多人认为他们是解决大多数问题的正确工具,但事实并非如此。此外,人们认为模式越复杂,它就越有可能解决问题,但复杂性为垃圾提供了更多的压缩空间,所以请保持简单。

此代码:

a.scan(/.+$/).map{ |s| "<p>#{s}</p>" }

依赖String的scan查看字符串并返回所有“\ n”终止行。如果该行不以“\ n”结尾,则返回它也是因为它是字符串的最后部分。 scan返回一个匹配数组,因此,在这种特殊情况下,这是一个由EOL终止的字符串片段数组,带有一个可能的尾随字符串片段。

将这些内容传递到map以将字符串片段嵌入<p>...</p>中,然后就完成了。

另一种完成同样事情的方法是利用字符串的gsub和块:

puts ary.map{ |a| 
  a.gsub(/.+$/) { |s| "<p>#{s}</p>" }
}
# >> <p>Lorem ipsum dolor sit amet.</p>
# >> <p>Vestibulum laoreet erat id quam.</p>
# >> <p>Lorem ipsum dolor sit amet.</p>
# >> <p>Vestibulum laoreet erat id quam.</p>

对于与模式匹配的每个实例,gsub会将匹配的文本传递给块。从那里开始,这是另一个简单的字符串插值。