2011-01-16 35 views
8

Tôi có trường văn bản blob trong cột MySQL có chứa HTML. Tôi phải thay đổi một số đánh dấu, vì vậy tôi figured tôi sẽ làm điều đó trong một kịch bản ruby. Ruby không liên quan ở đây, nhưng sẽ rất tuyệt khi thấy câu trả lời với nó. Đánh dấu trông như sau:tìm kiếm và thay thế bằng ruby ​​regex

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

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

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

tôi cần phải thay đổi chỉ là <h5>foo</h5> khối đầu tiên của mỗi văn bản để <h2>something_else</h2> khi rời khỏi phần còn lại của chuỗi một mình.

Dường như không thể có được chế độ PCRE phù hợp, sử dụng Ruby.

+2

Tôi yêu cầu bạn xem xét sử dụng trình phân tích cú pháp HTML thay vì sử dụng regex cho html. Như đã nói [nhiều] (http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags), [nhiều] (http: // stackoverflow. com/questions/590747/using-regular-expressions-to-parse-html-why-not), [nhiều] (http://stackoverflow.com/questions/6751105/why-its-not-possible-to-use -regex-to-parse-html-xml-a-chính thức-giải thích-in-la? lq = 1) lần trước, các trình phân tích cú pháp Regex không có khả năng phân tích chính xác HTML. –

+0

Cụ thể, tôi khuyên bạn nên sử dụng [Nokogiri] (http://nokogiri.org) để tải HTML của bạn, thao tác nó, và sau đó phát ra kết quả. – Phrogz

Trả lời

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

Sử dụng String#sub thay vì String#gsub chỉ làm thay thế đầu tiên xảy ra. Nếu bạn cần phải tự động chọn những gì 'foo' là, bạn có thể sử dụng chuỗi suy trong literals regex:

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

Sau đó, một lần nữa, nếu bạn biết những gì 'foo' là, bạn không cần một regex:

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

hoặc thậm chí:

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

Nếu bạn cần phải chạy mã để tìm ra sự thay thế, bạn có thể sử dụng mẫu khối phụ:

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 
+0

câu trả lời tuyệt vời, cảm ơn bạn – Alp

+0

giúp tôi rất nhiều .. thanx – Jaydipsinh

2

Sử dụng String.gsub với cụm từ thông <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>" 

Lưu ý, bạn có thể kiểm tra ruby ​​biểu hiện thường xuyên thoải mái in your browser.

+0

Liên kết bị hỏng. –

6

Bất cứ khi nào tôi phải phân tích cú pháp hoặc sửa đổi HTML hoặc XML, tôi tiếp cận với một trình phân tích cú pháp. Tôi gần như không bao giờ bận tâm với regex hoặc instring trừ khi nó hoàn toàn không có trí tuệ.

Dưới đây là làm thế nào để làm điều đó bằng Nokogiri, mà không cần bất kỳ 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 

Sau khi phân tích, đây là những gì Nokogiri đã trở lại từ đoạn:

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

Đây là sau khi chạy:

# >> <h2>something_else</h2> 
# >> <table><tbody></tbody></table><h5>bar</h5> 
# >> <table><tbody></tbody></table><h5>meow</h5> 
# >> <table><tbody></tbody></table> 
Các vấn đề liên quan