Ruby 我可以使用什么正则表达式将字符串拆分为单词,但将圆括号中的短语放在一起?

Ruby 我可以使用什么正则表达式将字符串拆分为单词,但将圆括号中的短语放在一起?,ruby,regex,Ruby,Regex,我想像这样拆分一个字符串: my_string = "I want to split this (these should stay together) correctly" 并得出以下结果: ["I", "want", "to", "split", "this", "(these should stay together)", "correctly"] 我试过这个: my_string.split(/(?=[^\(]){1,} (?=[^\)]){1,}/) 但是圆括号内的元素被分开了。

我想像这样拆分一个字符串:

my_string = "I want to split this (these should stay together) correctly"
并得出以下结果:

["I", "want", "to", "split", "this", "(these should stay together)", "correctly"]
我试过这个:

my_string.split(/(?=[^\(]){1,} (?=[^\)]){1,}/)

但是圆括号内的元素被分开了。如何实现此目的?

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

/ +(?![^()]*\))/

i、 e


(?![^()]*\)
负向前看,这意味着如果空格后跟0个或多个非圆括号字符和右圆括号,则不匹配空格,因此不匹配
(…)

拆分
是错误的工具。使用
扫描

my_string.scan(/\([^)]*\)|\S+/)
# => ["I", "want", "to", "split", "this", "(these should stay together)", "correctly"]
如果平衡圆括号可以与要组合在一起的其他非空格字符相邻,则您可能需要此圆括号,它通常适用于:

my_string.scan(/(?:\([^)]*\)|\S)+/)

通常,当分隔符可以用简单模式表示时,请使用
split
。当内容可以用简单模式表示时,使用
scan

可能需要分两步进行,以保持正则表达式的简单性:

my_string.scan(/\([^)]*\)|\S+/)
# => ["I", "want", "to", "split", "this", "(these should stay together)", "correctly"]
first, middle, last = my_string.partition /\(.*\)/
[*first.split, middle, *last.split]
  #=> ["I", "want", "to", "split", "this", "(these should stay together)",
  #    "correctly"]
另一个例子:

first, middle, last = "x (x(x(x)x)x) x".partition /\(.*\)/
[*first.split, middle, *last.split]
  #=> ["x", "(x(x(x)x)x)", x"]
但它在这里失败了:

first, middle, last = "x (x)x(x) x".partition /\(.*\)/
[*first.split, middle, *last.split]
  #=> [ "x, "(x)x(x)", "x"]

假设需要
[“x”,“x”,“x”,“x”,“x”],“x”]

出于好奇:

my_string.gsub(/\(.+?\)/) { |m| m.gsub ' ', ' ' }.split(/ +/)
尝试将上述代码复制粘贴到IRB中,并继续关注:

#⇒ ["I", "want", "to", "split", "this", 
#   "(these should stay together)", "correctly"]
:)

NB这是一个玩笑,请不要在生产中使用

正如@sawa所建议的,这是一种逃避,因此,为了使这个答案正确,我们应该将所有内容转换回正常空间:

    my_string.gsub(/\(.+?\)/) { |m| m.gsub ' ', ' ' }
             .split(/ +/)
             .gsub ' ', ' '

是否保证FSM会按照列出的顺序尝试或匹配?mudasobwa是的。顺序很重要。这将在嵌套括号上返回意外(IMHO)结果。@mudasobwa Correct。我认为情况并非如此。使用稍微复杂一点的正则表达式,可以捕获嵌套的括号。我的例子中没有嵌套的括号,所以这是可行的,但是绑定到这个非常具体的示例(即,只能有一个平衡的括号)。但你是对的。分多个步骤执行可以使正则表达式更简单。实际上,使用
split
可以捕获分隔符以及中间的子字符串,并使用
each_cons(2)
,您可以概括您的答案行以允许任意数量的平衡括号。@sawa,
*
贪婪这一事实难道不能解决你的担忧吗?我可能没有领会你的意思。一个有问题字符串的示例?对。您必须使用
[^)]
或非贪婪来修复该部分。代码中有一个有问题的字符串是
“foo bar(A b)baz(c d)foo”
。我不知道
m.gsub'',''
在做什么。但它是有效的。其中一个是制表符还是非ASCII空格?当然可以,但事实上你不应该对这个答案投赞成票。这是欺骗。ASCII-8不可破坏空间,是的。你的方法没有错。认真地你为什么评论不使用它?这是一个非常干净的想法。这个想法可以看作是某种逃避。@sawa那么我至少应该把这些空间转换回去。我将更新答案。您可以使用可见的内容(但在普通文本中很少使用)使其更易于理解。如果字符串是
“x((x)x”
,您是否希望
[“x”、“((x)”、“x”]
[“x”、“(,“(x)”、“x”]