如何删除第一段中的所有内容并使用正则表达式

时间:2017-05-10 18:59:10

标签: ruby-on-rails ruby regex

我试图摆脱第一段和最后一段中的所有额外<br>

例如:

st = "<p><br><br><br><br>apple</p>
     <p>bananas</p>
     <p>orange<br><br><br><br><br></p>
     <p>tomatoes</p>
     <p>berry<br><br><br><br><br><br></p>"

我希望最终得到这个:

        "<p>apple</p>
         <p>bananas</p>
         <p>orange<br><br><br><br><br></p>
         <p>tomatoes</p>
         <p>berry</p>"

我的目标是单独留下<br>中间段落(例如橙色段落)并删除所有第一段<br>,并将所有段落结束。

我试过这个正则表达式:

st.sub(/^((<p>)|<br( \/)?>)*|(<p>|<br( \/)?>|< \/p>)*$/, '')

我明白了:

=>  "<p>apple</p>
     <p>bananas</p>
     <p>orange<br><br><br><br><br></p>
     <p>tomatoes</p>
     <p>berry<br><br><br><br><br><br></p>"

我无法删除重复<br>的最后一段。

3 个答案:

答案 0 :(得分:4)

不要使用正则表达式。而是使用解析器:

require 'nokogiri'

doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p><br><br><br><br>apple</p>
<p>bananas</p>
<p>orange<br><br><br><br><br></p>
<p>tomatoes</p>
<p>berry<br><br><br><br><br><br></p>
EOT

p_tags = doc.search('p')
[:first, :last].each { |s| p_tags.send(s).search('br').remove }
doc.to_html

这会导致片段看起来像:

# => "<p>apple</p>\n" +
#    "<p>bananas</p>\n" +
#    "<p>orange<br><br><br><br><br></p>\n" +
#    "<p>tomatoes</p>\n" +
#    "<p>berry</p>\n"

解析器更能够应对更改HTML,因此,如果您要进行任何HTML更改或抓取它,可以获得回报以了解如何使用它们。

在没有解析器或复杂正则表达式的情况下执行所需操作的另一种方法是:

str = <<EOT
<p><br><br><br><br>apple</p>
<p>bananas</p>
<p>orange<br><br><br><br><br></p>
<p>tomatoes</p>
<p>berry<br><br><br><br><br><br></p>
EOT

str_lines = str.lines
[0, -1].each { |i| str_lines[i].gsub!(/<br>/, '') }
puts str_lines.join

导致同样的事情。

第一种方法的优势在于它不会关心<br>是否像HTML5或<br/>一样神秘地更改为<br >

最后,如果你再次坚持使用更长,更复杂的模式,至少要简化它:

puts str.sub(/\A<p>(?:<br>)+/, '<p>').sub(/(?:<br>)+<\/p>\Z/, '</p>')

再次导致同样的事情。

正则表达式对某些任务很有用,但它们不适合标记。如果坚持使用正则表达式,那么就像以后的解决方案一样简化问题,因为它降低了模式的复杂性,从而提高了可读性并简化了维护。

答案 1 :(得分:2)

st = st.gsub(/(?<=\A<p>)(<br\/?>)+|(<br\/?>)+(?=[<]\/p>\Z)/, '')

由管道(OR)分开的2个部分:

1)(?<=\A<p>)(<br\/?>)+匹配字符串开头(<br>)和\A标记后的1个或多个<p>

2)(<br\/?>)+(?=[<]\/p>\Z)匹配匹配字符串末尾<br>结束标记之前的{1}个</p> \Z

和gsub因为我们想要替换字符串中的所有匹配项,而不仅仅是第一个 g 子中的g代表 g lobal。

答案 2 :(得分:1)

我建议一些易于理解,测试和维护的简单方法。

str =<<-_
<p><br><br><br><br>apple</p>
<p>bananas</p>
<p>orange<br><br><br><br><br></p>
<p>tomatoes</p>
<p>berry<br><br><br><br><br><br></p>
_
  #=> "<p><br><br><br><br>apple</p>\n<p>bananas</p>\n<p>orange<br><br><br><br><br></p>\n<p>tomatoes</p>\n<p>berry<br><br><br><br><br><br></p>\n"

first, *mid, last = str.lines    
first.gsub('<br>', '') << mid.join << last.gsub('<br>', '')
  #=> "<p>apple</p>\n<p>bananas</p>\n<p>orange<br><br><br><br><br></p>\n<p>tomatoes</p>\n<p>berry</p>\n" 
puts s
<p>apple</p>
<p>bananas</p>
<p>orange<br><br><br><br><br></p>
<p>tomatoes</p>
<p>berry</p>

请注意

first
  #=> "<p><br><br><br><br>apple</p>\n" 
mid
  #=> ["<p>bananas</p>\n",
  #    "<p>orange<br><br><br><br><br></p>\n",
  #    "<p>tomatoes</p>\n"]
last
  #=> "<p>berry<br><br><br><br><br><br></p>\n"