【问题标题】:How do I replace consecutive occurrences of white space in each element of my array?如何替换数组的每个元素中连续出现的空白?
【发布时间】:2017-09-20 12:12:51
【问题描述】:

使用 Ruby 2.4。我有一个字符串数组。我想从数组中每个项目的末尾剥离非中断和中断空间,并将多个连续出现的空白替换为单个空白。我以为下面是方法,但我得到一个错误

 > words = ["1", "HUMPHRIES \t\t\t\t\t\t\t\t\t\t\t\t\t\t, \t\t\t\t\t\t\t\t\t\t\t\t\tJASON", "328", "FAIRVIEW, OR (US)", "US", "M", " 27 ", "00:27:30.00 \t\t\t\t\t\t\t\t\t\t\t \n"]

 > words.map{|word| word ? word.gsub!(/\A\p{Space}+|\p{Space}+\z/, '').gsub!(/[[:space:]]+/, ' ') : nil }
NoMethodError: undefined method `gsub!' for nil:NilClass
    from (irb):4:in `block in irb_binding'
    from (irb):4:in `map'
    from (irb):4
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.2/lib/rails/commands/console.rb:65:in `start'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.2/lib/rails/commands/console_helper.rb:9:in `start'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.2/lib/rails/commands/commands_tasks.rb:78:in `console'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.2/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.2/lib/rails/commands.rb:18:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'

如何正确替换连续出现的空白并将其从数组中的每个单词中去除?

【问题讨论】:

标签: arrays ruby regex


【解决方案1】:

用简单的gsub而不是gsub!来做

words.map do |w|
  #respond_to?(:gsub) if you are not sure that array only from strings
  w.gsub(/(?<=[^\,\.])\s+|\A\s+/, '') if w.respond_to?(:gsub)
end

因为如果不更改字符串,gsub! 可以返回 nil,然后您尝试使用 nil 再次执行 gsub!。这就是您收到undefined method gsub!' for nil:NilClass 错误的原因。

来自gsub! ruby​​ doc 中的解释:

在原地执行 String#gsub 的替换,返回 str,或 如果没有进行替换,则为零。如果没有阻塞且没有替换 给出,而是返回一个枚举器。

正如 cmets \s 中提到的 @CarySwoveland 不处理不间断空格。要处理它,您应该使用[[:space:]] insted of \s

【讨论】:

  • 我不明白你的代码。当它运行时selfmain 并且main 没有方法gsub。此外,它不会删除规范要求的不间断空格(例如,Unicode'a non-break space\00A0)。
  • @CarySwoveland 谢谢,这是上次编辑后gsub 调用的拼写错误。问题不在这个问题的正则表达式中,但你是对的 - \s 与不间断空格不匹配,但在 [[:space:]] 上更改 \s 很容易处理
【解决方案2】:

我假设每个字符串发送时的所有空白和不间断空格都将被删除,剩下的所有子字符串的空白字符和不间断空格都将被一个空格替换。 (Natalia,如果这不正确,请在评论中告诉我。)

words =
  ["1",
   "HUMPHRIES \t\t\t\, \t\t\t\t\t\t\t\t\t\t\t\t\tJASON",
   " M\u00A0    \u00A0",
   "    27 ",
   "00:27:30.00 \t\t\t\t\t\t\t\t\t\t\t \n"]

R = /
    [[:space:]]     # match a POSIX bracket expression for one character
    (?=[[:space:]]) # match a POSIX bracket expression for in a positive lookahead
    |               # or
    [[:space:]]+    # match a POSIX bracket expression one or more times
    \z              # match end of string
    /x              # free-spacing regex definition mode

words.map { |w| w.gsub(R, '').gsub(/[[:space:]]/, ' ') }
  #=> ["1", "HUMPHRIES , JASON", " M", " 27", "00:27:30.00"]

请注意,POSIX [[:space:]] 包括 ASCII 空格和 Unicode 的不间断空格字符 \u00A0

要了解为什么需要第二个 gsub,请注意

words.map { |w| w.gsub(R, '') }
  #=> ["1", "HUMPHRIES\t,\tJASON", " M", " 27", "00:27:30.00"] 

【讨论】:

    【解决方案3】:

    您可以使用以下内容:

    words.map { |w| w.gsub(/(?<=[^\,\.])\s+/,'') }
     #=> ["1", "HUMPHRIES, JASON", "328", "FAIRVIEW,
     #     OR(US)", "US", "M", " 27", "00:27:30.00"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-16
      • 2021-02-07
      • 2019-01-11
      • 2017-09-27
      • 2021-06-18
      • 2010-09-24
      • 2013-12-05
      • 2019-01-07
      相关资源
      最近更新 更多