2011-01-16 17 views
8

Ich habe ein Textblobfeld in einer MySQL-Spalte, die HTML enthält. Ich muss etwas vom Markup ändern, also dachte ich, ich mache es in einem Ruby-Skript. Ruby ist hier irrelevant, aber es wäre schön, eine Antwort zu sehen. Das Markup sieht wie folgt aus:Suchen und Ersetzen mit Ruby Regex

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

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

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

ich gerade den ersten <h5>foo</h5> Block jeden Text <h2>something_else</h2> ändern muß, während der Rest der allein Zeichenfolge zu verlassen.

Scheint nicht die richtige PCRE-Regex zu bekommen, mit Ruby.

+2

Ich flehe Sie an, einen HTML-Parser anstelle von Regex für HTML zu verwenden. Wie es schon gesagt wurde [http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags], [viele] (http: // stackoverflow. com/questions/590747/using-reguläre Ausdrücke-zu-analysieren-html-why-not), [viele] (http://stackoverflow.com/questions/6751105/why-its-not-possible-use-use -regex-to-parse-html-xml-a-formale-Erklärung-in-la? lq = 1) mal zuvor, Regex-Parser sind nicht in der Lage, HTML genau zu analysieren. –

+0

Insbesondere empfehle ich, [Nokogiri] (http://nokogiri.org) zu verwenden, um Ihren HTML-Code zu laden, ihn zu manipulieren und dann das Ergebnis auszugeben. – Phrogz

Antwort

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>') 

Mit String#sub statt String#gsub Ursachen nur der erste Ersatz auftreten. Wenn Sie dynamisch wählen müssen, was ‚foo‘ ist, können Sie String-Interpolation in Regex-Literale verwenden:

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

Dann wieder, wenn Sie wissen, was ‚foo‘ ist, brauchen Sie nicht einen regulären Ausdruck:

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

oder sogar:

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

Wenn Sie Code ausführen müssen den Austausch, um herauszufinden, können Sie die Blockform von Unter verwenden:

+0

ausgezeichnete antwort, danke – Alp

+0

hilf mir viel .. danke – Jaydipsinh

2

Verwenden String.gsub mit dem regulären Ausdruck <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>" 

Hinweis, können Sie reguläre Ausdrücke bequem in your browser rubin testen.

+0

Link ist kaputt. –

6

Immer wenn ich HTML oder XML parsen oder ändern muss, erreiche ich einen Parser. Ich beschäftige mich fast nie mit Regex oder Instring, es sei denn, es ist absolut ein Kinderspiel.

Hier ist, wie es zu tun Nokogiri verwenden, ohne regex:

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 

Nach Parsen, ist es das, was Nokogiri aus dem Fragment zurückgekehrt ist:

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

Dies ist nach dem Laufen:

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