【问题标题】:How to strip leading and trailing quote from string, in Ruby如何在Ruby中从字符串中去除前导和尾随引号
【发布时间】:2010-08-10 20:43:16
【问题描述】:

我想在 Ruby 中从字符串中去除前导引号和尾随引号。引号字符将出现 0 或 1 次。例如,以下所有内容都应转换为 foo,bar:

  • "foo,bar"
  • "foo,bar
  • foo,bar"
  • foo,bar

【问题讨论】:

标签: ruby regex string


【解决方案1】:

您也可以使用chomp 函数,但不幸的是,它只适用于字符串的末尾,假设有一个反向 chomp,您可以:

'"foo,bar"'.rchomp('"').chomp('"')

实现rchomp 很简单:

class String
  def rchomp(sep = $/)
    self.start_with?(sep) ? self[sep.size..-1] : self
  end
end

请注意,您也可以使用效率稍低的版本进行内联:

'"foo,bar"'.chomp('"').reverse.chomp('"').reverse

编辑:从 Ruby 2.5 开始,rchomp(x) 可以在名称 delete_prefix 下使用,chomp(x) 可以在 delete_suffix 下使用,这意味着您可以使用

'"foo,bar"'.delete_prefix('"').delete_suffix('"')

【讨论】:

  • 有趣的方法。我希望有人提供涉及数组索引 [0] 和 [-1] 的答案,但忘记了 chomp,这是一个明显更好的解决方案。我觉得你的答案比我的好。
  • rchomp 和 lchomp 应该是必需的函数,该死!
  • delete_suffixdelete_prefix 方法在那里,也许在写这个答案时它们不存在
  • @Sundeep 感谢您指出这一点。我已将其添加到答案中。
【解决方案2】:

我可以使用 gsub 搜索前导或尾随引号并将其替换为空字符串:

s = "\"foo,bar\""
s.gsub!(/^\"|\"?$/, '')

正如下面 cmets 所建议的,更好的解决方案是:

s.gsub!(/\A"|"\Z/, '')

【讨论】:

  • 一些提示:没有必要转义Regexp 中的引号,因为引号在Regexp 中没有任何特殊含义。此外,^$ 锚定到 string 的开头和结尾,它们锚定到 line 的开头和结尾我>。从你的问题中不清楚你想要哪一个:如果你想从字符串的开头和结尾删除引号,你需要使用 \A\Z 代替。最后,您可以通过用单引号分隔字符串来摆脱双引号的转义(以及令人困惑的双引号)。
  • 总而言之,它看起来像这样:` s = '"foo,bar"'; s.gsub!(/\A"|\Z"$/, '') ` (我忘记了:也没有必要让匹配成为可选的。如果不匹配,那么什么都不会被替换。)
  • @Jörg,你不是说s.gsub!(/\A"|"\Z/, '')吗?
  • @grddev:是的,当然。这个评论框是一个糟糕的 IDE :-)
【解决方案3】:

像往常一样,每个人都会先从工具箱中获取正则表达式。 :-)

作为替代方案,我建议您查看.tr('"', '')(又名“翻译”),在这种用法中,它实际上是在去除引号。

【讨论】:

  • 假设字符串中间没有"
  • 根据 OP 给出的示例,只有前导/尾随双引号,因此这是一个安全的假设。
  • 这不是一个安全的假设,但我没有明确说明字符串中可能有引号。不过,这是一个很好的答案,绝对值得我 +1。
  • 他指定了“一个字符串”。字符串可以包含任意字符,包括引号。
【解决方案4】:

另一种方法是

remove_quotations('"foo,bar"')

def remove_quotations(str)
  if str.start_with?('"')
    str = str.slice(1..-1)
  end
  if str.end_with?('"')
    str = str.slice(0..-2)
  end
end 

它没有 RegExps 和 start_with?/end_with?可读性很好。

【讨论】:

    【解决方案5】:

    让我感到沮丧的是 strip 只适用于空白。我需要剥离各种字符!这是一个可以解决这个问题的字符串扩展:

    class String
      def trim sep=/\s/
        sep_source = sep.is_a?(Regexp) ? sep.source : Regexp.escape(sep)
        pattern = Regexp.new("\\A(#{sep_source})*(.*?)(#{sep_source})*\\z")
        self[pattern, 2]
      end
    end
    

    输出

    '"foo,bar"'.trim '"'         # => "foo,bar"
    '"foo,bar'.trim '"'          # => "foo,bar"
    'foo,bar"'.trim '"'          # => "foo,bar"
    'foo,bar'.trim '"'           # => "foo,bar"
    
    '  foo,bar'.trim             # => "foo,bar"
    'afoo,bare'.trim /[aeiou]/   # => "foo,bar"
    

    【讨论】:

      【解决方案6】:

      假设引号只能出现在开头或结尾,您可以删除所有引号,无需任何自定义方法:

      '"foo,bar"'.delete('"')
      

      【讨论】:

      • 非常感谢任何关于为什么这被否决的解释。
      【解决方案7】:

      我想要相同的,但对于 url 路径中的斜杠,它可以是 /test/test/test/(因此它在中间有剥离字符)并最终想出了这样的东西来避免正则表达式:

      '/test/test/test/'.split('/').reject(|i| i.empty?).join('/')
      

      在这种情况下显然可以转换为:

       '"foo,bar"'.split('"').select{|i| i != ""}.join('"')
      

      '"foo,bar"'.split('"').reject{|i| i.empty?}.join('"')
      

      【讨论】:

      • 这个问题七岁半了。路要走,用新方法添加答案!非常值得我 +1。
      【解决方案8】:

      正则表达式可能非常繁重并导致一些时髦的错误。如果您不处理大量字符串并且数据非常统一,则可以使用更简单的方法。

      如果你知道字符串有开头和前导引号,你可以拼接整个字符串:

      string  = "'This has quotes!'"
      trimmed = string[1..-2] 
      puts trimmed # "This has quotes!"
      

      这也可以变成一个简单的函数:

      # In this case, 34 is \" and 39 is ', you can add other codes etc. 
      def trim_chars(string, char_codes=[34, 39])
          if char_codes.include?(string[0]) && char_codes.include?(string[-1])
              string[1..-2]
          else
              string
          end
      end
      

      【讨论】:

      • 很遗憾,这并不能回答提出的问题。
      • 正则表达式不会导致一些时髦的错误。糟糕的代码会导致一些奇怪的错误。
      【解决方案9】:

      您可以使用scan 去除非可选引号:

      '"foo"bar"'.scan(/"(.*)"/)[0][0]
      # => "foo\"bar"
      

      【讨论】:

      • 给出的三个例子都失败了。
      • 啊,没有注意到引号在您的情况下是可选的。不过,这对于要求略有不同的人会有所帮助。
      猜你喜欢
      • 2011-10-02
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      相关资源
      最近更新 更多