【问题标题】:Ruby replace only exact matching string with another stringRuby 只用另一个字符串替换完全匹配的字符串
【发布时间】:2023-04-10 01:07:01
【问题描述】:

我该如何解决以下问题?

我有一个 html 字符串,如下所示:

<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>

现在我只想替换例如

"aaa" 

"<div class='special'>aaa</div>"

替换后的新字符串:

<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>

所以我想要一个通用替换器,它只替换一个完全匹配的字符串。 “aaa”只是一个例子。它也可以是“bb”或“两个词”(=> 两个词,所以我认为 text.split 不起作用)。

有人对这种动态查找、匹配和替换器有想法吗?

我已经尝试过如下:

items = ["aaa", "a", "aa", "aa b", "c"]
text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
words = text.split => ["<p>aaa,", "b", "aa", "aaaaa?<br/>Next", "possible", "text", "b", "bb", "aa", "b.</p>"]
new_words = []

words.each do |w|
   items.each do |item|
     if w == item
       w = '<div class="special">#{item}</div>'
     end
   end
  new_words << w
end
text = new_words.join(" ")

结果:

"<p>aaa, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa</div> b.</p>"

但应该是:

"<p><div class='special'>aaa</div>, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa b</div>.</p>"

我最大的问题是:

  • 特殊字符,如“,.?()%€” - 字符串末尾的字符 => 示例中的“aaa”
  • 具有相同部分的子字符串 => 如“aaa”和“aa”
  • 两个词作为一个项目 => 就像示例中的“aa b”

有人可以解决我的问题吗?

编辑:某些东西只是我的替代品的占位符。我真正的替代品也可能是:

%Q( <dfn title="#{strip_tags item.text}">#{item.name}</dfn> )

item.text 可以是所有内容 => 也可以包含“aaa” item.name 例如“aaa”

所以多个 gsub 会替换已经替换的内容。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    目前尚不清楚aaa 是单个实例还是多个实例,以及您是希望将它们全部替换,还是只替换第一个。

    这将只替换第一个:

    text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
    text.sub(/\b(aaa)\b/, %q"<div class='special'>\1</div>")
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
    

    这将替换所有匹配项:

    text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" * 2
    => "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
    
    text.gsub(/\b(aaa)\b/, %q"<div class='special'>\1</div>")
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
    

    您可以将"aaa" 放入一个变量中,然后通过将该目标插入到模式中来找到它:

    target = 'aaa'
    text.gsub(/\b(#{ target })\b/, %q"<div class='special'>\1</div>")
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
    

    正则表达式有\b(分词)标记,这使得定义单词或子字符串匹配变得容易。您也可以将"aaa" 替换为多个单词。

    【讨论】:

      【解决方案2】:

      您正在寻找String#sub(不是gsub

      s = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
      # => "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
      match = "aaa"
      # => "aaa"
      replacement = "<div class='special'>aaa</div>"
      # => "<div class='special'>aaa</div>"
      s.sub match, replacement
      # => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>"
      "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" == _
      # => true
      

      【讨论】:

      • 但如果字符串是“

        aaa, b aa aaaaa?
        下一个可能的文本 b bb aa b.aaa.

        ”那将不起作用?
      • 如果你保持match 变量相同的内容,它不会工作。如果你有不同的字符串,那么你可以通过match = "b bb"(或您希望匹配的字符串中的任何内容)更改match 变量,或者,可能更好的是,编辑您的问题并让我们知道字符串如何变化以及您如何知道要抓取的部分.
      【解决方案3】:

      我会使用正则表达式,Rubular 是学习和测试表达式的好地方。有关如何使用 gsub 的更多信息,请查看Jayfields Blog post。这可能不适合此问题的所有用例,因此您可能需要对其进行修改。

          str.gsub /^<p>a{3}/, "<div class='special'>aaa</div>"
      
      
         What this says is starting at the beginning of the string (^) 
         find <p> and 3 assurances of the letter a.
      

      【讨论】:

      • 它应该是 sub 而不是 gsub,因为 OP 只想要第一个匹配项并且没有指定它总是在标签旁边。
      【解决方案4】:

      这是您想要的替换方法(当然是使用 gsub):

      def replacer(orig,pattern,replace)
        orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s
      end
      
      2.0.0dev :001 > def replacer(orig,pattern,replace)
      2.0.0dev :002?>     orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s
      2.0.0dev :003?>   end
       => nil 
      2.0.0dev :004 >  replacer("<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>", "aaa", "<div class='special'>aaa</div>")
       => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-17
        • 2020-01-11
        • 1970-01-01
        • 1970-01-01
        • 2021-07-11
        • 1970-01-01
        • 2019-01-12
        相关资源
        最近更新 更多