试图将字符串分割成单词或“带引号的单词”,并希望在结果数组中保留引号。

13

我试图将像 Presentation about "Test Driven Development" 这样的字符串拆分成以下数组:

[ 'Presentation',
  'about',
  '"Behavior Driven Development"' ]

我尝试使用 CSV::parse_line(string, col_sep: ' '),但结果是

[ 'Presentation',
  'about',
  'Behavior Driven Development' ] # I'm missing the quotes here

我也尝试了一些正则表达式的技巧,但我还是一个初学者,没有成功。我猜这对于专业人士来说相当简单,所以也许有人可以指点我正确的方向?谢谢。


我修复了我的回答。现在应该可以为您工作了。 - Linuxios
哈!CSV 正是我所需要的。 - Chris
3个回答

22

您可以使用以下正则表达式split

str = 'Presentation about "Test Driven Development"'
p str.split(/\s(?=(?:[^"]|"[^"]*")*$)/)
# => ["Presentation", "about", "\"Test Driven Development\""]

如果空格后面的文本中包含偶数个",则会按空格拆分。请注意,此版本仅在所有字符串都被正确引用时才有效。

另一种解决方案使用scan来读取字符串的各个部分(除空格外):

p str.scan(/(?:\w|"[^"]*")+/)
# => ["Presentation", "about", "\"Test Driven Development\""]

谢谢,运行得很好!正则表达式就像魔法一样……我会尝试分解并理解它们。 - Joshua Muheim
供您参考,我使用以下代码来移除空元素并去除引号和空格:"a b 'c d '".split(/\s(?=(?:[^'"]|'[^']'|"[^"]")*$)/).select {|s| not s.empty? }.map {|s| s.gsub(/(^ +)|( +$)|(^["']+)|(["']+$)/,'')} - Keymon

4

为了补充Howard之前的答案,你可以添加以下方法:

class String
  def tokenize
    self.
      split(/\s(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/).
      select {|s| not s.empty? }.
      map {|s| s.gsub(/(^ +)|( +$)|(^["']+)|(["']+$)/,'')}
  end
end

结果如下:

> 'Presentation      about "Test Driven Development"  '.tokenize
=> ["Presentation", "about", "Test Driven Development"]

0

这里:

"Presentation about \"Test Driven Development\"".scan(/\s?\w+\s?|"[\w\s]*"/).map {|s| s.strip}

好的,我撤回我的-1。请注意现在结果中包括空格。 - Howard
.scan(/(?:\S|"[^"]*")+/)是什么意思? - Howard
谢谢!有趣的是,攻击问题的方式有很多种。 - Joshua Muheim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接