Ruby - gsub br 标签到 \n\n for API,但包括任何空格

Ruby - gsub br tags to \n\n for API, but including any whitespace

我的客户数据中有 <br> 标签,我需要在我的 Rails API 中用“\n\n”替换 React Native 应用程序。

有时在 <br> 标签之前或之后,或两者都有空格。

我正在寻找一个 gsub 来表示“任何 <br> 标记,并且还包括它前后的任何空格,替换为 '\n\n'。

现在我在做:

module ApiHelper
  def parse_newlines(string)
    string = string.gsub('<br>', '\n\n')
    string = string.gsub(' <br>', '\n\n')
    string = string.gsub('<br> ', '\n\n')
    string = string.gsub(' <br> ', '\n\n')
  end
end

有没有更干净的东西?

编辑:谢谢大家。我想接受 Gavin 和 Tin Man 的回答...Gavin 因为他给了我肮脏的解决方案,但是 Tin Man 对使用 Nokogiri 的更稳健方式的 great/in 深度解释...

第二次编辑:我收回它。铁皮人...使用 Nokogiri 实际上更具可读性。您关于在评论中使用正则表达式的论点是有效的。最后你的代码更容易理解。给你公认的答案,即使我现在使用 Gavin 的。

这样做就可以了:

module ApiHelper
  def parse_newlines(string)
    # Handles <br>, <br/>, <br />
    string.gsub(/\s*<br\s*?\/?>\s*/, "\n\n")
  end
end

# irb
> parse_newlines("     <br>      ")
=> "\n\n"
> parse_newlines("     <br />      ")
=> "\n\n"
> parse_newlines("<br />")
=> "\n\n"

您可以试试:

string = 'Lorem <br> Ipsum'
puts string.gsub(/\s(<br>)\s/, '\n\n')
# => Lorem\n\nIpsum
puts string.gsub(/\s(<br>)\s/, "\n\n")
# Lorem
# 
# Ipsum

并注意 '\n\n'"\n\n" 之间的区别。

module ApiHelper
  def parse_newlines(string)
    string.gsub(/\s*<br>\s*/, "\n\n")
  end
end

当弄乱 HTML 或 XML 时,最好使用解析器。我将从以下内容开始:

require 'nokogiri'

doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p>this<br>is<br> some <br>
text<br>and<br >some<br/>more</p>
EOT

doc.search('br').each { |br| br.replace("\n\n") }
doc.to_html
# => "<p>this\n" +
#    "\n" +
#    "is\n" +
#    "\n" +
#    " some \n" +
#    "\n" +
#    "\n" +
#    "text\n" +
#    "\n" +
#    "and\n" +
#    "\n" +
#    "some\n" +
#    "\n" +
#    "more</p>\n"
浏览器显示的HTML中的

白色space被浏览器吞噬所以space运行,否则多个returns将减少为单个space 或单行,除非你用 <pre> 标签包裹它或做类似的事情。

如果您确实需要在插入换行符前后删除 spaces,我会使用额外的步骤:

require 'nokogiri'

doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p>this<br>is<br> some <br>
text<br>and<br >some<br/>more</p>
EOT

doc.search('p').each do |p|
  p.inner_html = p.inner_html.gsub(/ +</, '<').gsub(/> +/, '>')
end 

doc.to_html
# => "<p>this<br>is<br>some<br>\n" +
#    "text<br>and<br>some<br>more</p>\n"

doc.search('br').each { |br| br.replace("\n\n") }
doc.to_html
# => "<p>this\n" +
#    "\n" +
#    "is\n" +
#    "\n" +
#    "some\n" +
#    "\n" +
#    "\n" +
#    "text\n" +
#    "\n" +
#    "and\n" +
#    "\n" +
#    "some\n" +
#    "\n" +
#    "more</p>\n"

注意:从技术上讲,<br> 等同于单个“\n”,而不是“\n\n”。 <p> 将是两个新行,因为那构成了一个段落。