2014-06-27 51 views
0

我需要幫助正則表達式。我的任務與Twitter的主題標籤非常相似:我有一個字符串,文字盯着#。例如:如何找到不在<a>標籤內的單詞?

foo #bar hello 

我與鏈接替換井號標籤之前保存到數據庫並獲取字符串是這樣的:

foo <a href="bar">#bar</a> 

後,有時我需要重新解析字符串,我不想要在<a>標籤內替換#bar兩次。我需要regexp應該找到一個字開始#和放置在>,<,></a>內。

+0

是這個'富#bar'你期望的輸出:如果你想數也包括可以用這個? –

+0

'#bar'只會是一個深度嗎?因爲我認爲我有一個解決方案,只要這些解決方案不嵌套在任何其他標記中。 –

+0

當然還有一個經典的問題,你是否考慮過一個XML解析器? –

回答

0

從您的輸入獲得:

foo #bar hello 

到您的輸出:

foo <a href="bar">#bar</a> hello 

idempotently,這樣你就可以通過你的函數傳遞你的輸出回來了,它不會改變,你可以使用這個:

str1 = "foo #bar hello" 
str2 = 'foo <a href="bar">#bar</a> hello' 
replace_func = -> str { str.sub(/#(\w+)(?=[^<]*?(?:<[^\/]|$))/, '<a href="\1">#\1</a>')} 
replace_func[str1] 
replace_func[str2] 
# both return: "foo <a href=\"bar\">#bar</a> hello" 

Live Demo

另外引入nokogiri可以非常簡單地使用:

require 'nokogiri' 
doc = Nokogiri::XML('<p>' + you_string + '</p>') 
doc.search('//p').each do |node| 
    node.content = node.content.sub(/#\w+/) 
end 
0

與引入nokogiri的主要優點是,你可以很容易地使用XPath查詢檢查,如果一個文本節點沒有鏈接節點的祖先(可鏈接「T被嵌套),如果它含有至少一個#(也沒用到其它文本節點內搜索)

require 'nokogiri' 
doc = Nokogiri::HTML(html_doc) 

doc.search('//text()[not(ancestor::a) and contains(., "#")]').each do |txt| 
    txt.content.split(/(#\w+)/).each_with_index do |v, k| 
     if k%2 > 0 
      node = Nokogiri::XML::Node.new("a", doc) 
      node.content = v 
      node['href'] = "http://domain.com?usr=" + v[1..-1] 
     else 
      node = v 
     end 
     txt.before(node) 
    end 
    txt.remove 
end 

puts doc.to_html 

或多個簡單:

doc.search('//text()[not(ancestor::a) and contains(., "#")]').each do |txt| 
    txt.content.split(/(#\w+)/).each_with_index do |v, k| 
     if k%2 > 0 
      v = '<a href="http://domain.com?usr=' + v[1..-1] + '">' + v + '</a>' 
     end 
     txt.before(v) 
    end 
    txt.remove 
end 

注意:如果你需要處理一個完整的HTML文檔的唯一部分,你必須做出一點改變,使其作品(你需要用的HTML中根節點,使XPath查詢工作)

doc = Nokogiri::HTML::fragment('<div>' + html_doc + '</div>') 
doc.search('.//text()[not(ancestor::a) and contains(., "#")]').each do |txt| 

    txt.content.split(/(#\w+)/).each_with_index do |v, k| 
     if k%2 > 0 
      v = "<a href=\"http://mydomain.com?usr=#{v[1..-1]}\">#{v}</a>" 
     end 
     txt.before(v) 
    end 
    txt.remove 
end 
doc.xpath('*/node()').each do |node| 
    puts node.to_html 
end 
0

使用本:

/\<[^>]+\>[^<]*(\#[a-zA-Z]+)/ 

[A-ZA-Z]是字母,可能是在這個詞#後。

/\<[^>]+\>[^<]*(\#[a-zA-Z0-9]+)/ 
相關問題