0

我想附加</tag>到它丢失的每一行:

text = '<tag>line 1</tag>
        <tag>line2         # no closing tag, append
        <tag>line3         # no closing tag, append
             line4</tag>   # no opening tag, but has a closing tag, so ignore
        <tag>line5</tag>'

我试图创建一个正则表达式来匹配它,但我知道它是错误的:

text.gsub! /.*?(<\/tag>)Z/, '</tag>'

如何创建正则表达式以有条件地附加每一行?

4

4 回答 4

2

干得好:

text.gsub!(%r{(?<!</tag>)$}, "</tag>")

解释:

$表示行\z尾和字符串结束。\Z意思类似,但有复杂性。

(?<!)共同创造一个消极的后视。

于 2013-08-23T22:02:42.413 回答
0

鉴于提供的示例,我会做这样的事情:

text.split(/<\/?tag>/).
     reject {|t| t.strip.length == 0 }.
     map {|t| "<tag>%s</tag>" % t.strip }.
     join("\n")

您基本上将 和 视为记录分隔符,因此您可以拆分它们,拒绝任何空白记录,然后从提取的值构造一个新的组合字符串。当您不能指望换行符作为记录分隔符并且通常可以容忍丢失的标签时,这很有效。

但是,如果您坚持使用纯正则表达式解决方案,并且您的数据格式将始终与给定格式匹配(每行一条记录),则可以使用否定的lookbehind:

text.strip.gsub(/(?<!<\/tag>)(\n|$)/, "</tag>\\1")
于 2013-08-23T21:57:22.290 回答
0
text = '<tag>line 1</tag>
        <tag>line2        
        <tag>line3
        line4</tag>
        <tag>line5</tag>'

result = ""

text.each_line do |line|
  line.rstrip!
  line << "</tag>" if not line.end_with?("</tag>")
  result << line << "\n"
end

puts result

--output:--
<tag>line 1</tag>
        <tag>line2</tag>
        <tag>line3</tag>
        line4</tag>
        <tag>line5</tag>
于 2013-08-24T05:31:50.573 回答
0

一种可行的方法是:

/<tag>[^\n ]+[^>][\s]*(\n)/

这将返回所有在它们之前没有“>”的换行符。

换成“\n”,即

text.gsub!( /<tag>[^\n ]+[^>][\s]*(\n)/ , "</tag>\n")

如需更多润色,请尝试http://rubular.com/

于 2013-08-23T22:06:58.057 回答