-1

我正在尝试向<p>用户生成的文本添加标签来代替换行符。

这是我的代码:

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

替换工作与第一段的预期完全相同,但如果我添加额外的回车,它只会包装最后的文本块。看起来\Zand$不像我期望的那样匹配。

我究竟做错了什么?

这个:

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>
4

2 回答 2

1

尝试使用正则表达式

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

并替换为\\1

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


如果你的意思是你想在<p>and之间包装每一行</p>,那么你可以简单地使用:

/^(.+)$/

并替换为\\1

或使用正则表达式:

/([^\n\r]+)/
于 2013-09-18T17:35:12.287 回答
1

I'd do it like this:

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>

Both strings are returned the same way.

Regular expressions are not a magic wand you can wave to fix every problem. They have their uses, but too many people think that they're the right tool for most of their problems, and they're not. Also, people think that the more complex the pattern, the more likely it is that it'll fix the problem, but instead the complexity provides more places for junk to squish out, so keep them simple.

This code:

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

Relies on String's scan to look through a string and return all "\n" terminated lines. If the line doesn't end with "\n" it gets returned also because it's the final part of the string. scan returns an array of matches, so, in this particular situation, that'd be an array of string fragments terminated by the EOL with a possible trailing string-fragment.

Pass those through a map to embed the string-fragment inside <p>...</p> and you're done.

An alternate way to accomplish the same thing is to take advantage of String's gsub with a block:

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>

For each instance that matches the pattern, gsub will pass the matched text to the block. From there it's another simple string interpolation.

于 2013-09-18T18:28:19.093 回答