搜索并替换ruby正则表达式

时间:2011-01-16 01:46:13

标签: ruby regex

我在MySQL列中有一个包含HTML的文本blob字段。我必须改变一些标记,所以我想我会用ruby脚本来做。 Ruby在这里无关紧要,但是看到它的答案会很高兴。标记如下所示:

<h5>foo</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>bar</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>meow</h5>
  <table>
    <tbody>
    </tbody>
  </table>

我需要将每个文本的第一个<h5>foo</h5>块更改为<h2>something_else</h2>,同时保留字符串的其余部分。

使用Ruby似乎无法获得正确的PCRE正则表达式。

3 个答案:

答案 0 :(得分:31)

# The regex literal syntax using %r{...} allows / in your regex without escaping
new_str = my_str.sub( %r{<h5>[^<]+</h5>}, '<h2>something_else</h2>' )

使用String#sub代替String#gsub只会导致第一次替换。如果你需要动态选择'foo'是什么,你可以在正则表达式文字中使用字符串插值:

new_str = my_str.sub( %r{<h5>#{searchstr}</h5>}, "<h2>#{replacestr}</h2>" )

然后,如果你知道'foo'是什么,你不需要正则表达式:

new_str = my_str.sub( "<h5>searchstr</h5>", "<h2>#{replacestr}</h2>" )

甚至:

my_str[ "<h5>searchstr</h5>" ] = "<h2>#{replacestr}</h2>"

如果您需要运行代码来找出替换,您可以使用sub的块形式:

new_str = my_str.sub %r{<h5>([^<]+)</h5>} do |full_match|
  # The expression returned from this block will be used as the replacement string
  # $1 will be the matched content between the h5 tags.
  "<h2>#{replacestr}</h2>"
end

答案 1 :(得分:6)

每当我必须解析或修改HTML或XML时,我都会找到解析器。我几乎从不打扰正则表达式或instring,除非它绝对是一个明智的选择。

以下是使用Nokogiri的方法,没有任何正则表达式:

text = <<EOT
<h5>foo</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>bar</h5>
  <table>
    <tbody>
    </tbody>
  </table>

<h5>meow</h5>
  <table>
    <tbody>
    </tbody>
  </table>
EOT

require 'nokogiri'

fragment = Nokogiri::HTML::DocumentFragment.parse(text)
print fragment.to_html

fragment.css('h5').select{ |n| n.text == 'foo' }.each do |n|
  n.name = 'h2'
  n.content = 'something_else'
end

print fragment.to_html

解析之后,这就是Nokogiri从片段中返回的内容:

# >> <h5>foo</h5>
# >>   <table><tbody></tbody></table><h5>bar</h5>
# >>   <table><tbody></tbody></table><h5>meow</h5>
# >>   <table><tbody></tbody></table>

这是在运行之后:

# >> <h2>something_else</h2>
# >>   <table><tbody></tbody></table><h5>bar</h5>
# >>   <table><tbody></tbody></table><h5>meow</h5>
# >>   <table><tbody></tbody></table>

答案 2 :(得分:2)

String.gsub与正则表达式<h5>[^<]+<\/h5>

一起使用
>> current = "<h5>foo</h5>\n  <table>\n    <tbody>\n    </tbody>\n  </table>"
>> updated = current.gsub(/<h5>[^<]+<\/h5>/){"<h2>something_else</h2>"}
=> "<h2>something_else</h2>\n  <table>\n    <tbody>\n    </tbody>\n  </table>"

注意,您可以舒适地测试ruby正则表达式in your browser