分割字符串时忽略空捕获

时间:2018-07-09 16:41:19

标签: ruby regex

我有一个字符串:

Ayy ***lol* m8\nlol"

我不希望包含空捕获并产生:

["Ayy ", "**", "*", "lol", "*", " m8", "\n", "lol"]

我正在使用此正则表达式分割字符串:

/(?x)(\*\*|\*|\n|[.])/

这将产生:

["Ayy ", "**", "", "*", "lol", "*", " m8", "\n", "lol"]

3 个答案:

答案 0 :(得分:5)

这是您的regex的简化版本,与删除空字符串的方法链接在一起-使用String#split时在此不可避免,因为在'**中间有一个“空结果” *':

string = "Ayy ***lol* m8\nlol"


string.split(/(\*{1,2}|\n|\.)/).reject(&:empty?)
  #=> ["Ayy ", "**", "*", "lol", "*", " m8", "\n", "lol"] 

与您的模式有一些区别:

  • 我已删除(?x);这毫无用处。 Extended patterns对于忽略正则表达式中的空格和注释非常有用-您在此处都不会做任何操作。
  • \*\*|\*可以简化为\*{1,2}(或根据需要简化为\*\*?)。
  • [.]从技术上讲还不错,但是\.短了一个字符,我认为显示的意图更加清晰。

答案 1 :(得分:3)

使用包含捕获组的正则表达式进行拆分时,连续匹配始终会生成空数组项。

使用

而不是使用 matching 方法
arr = arr.reject { |c| c.empty? }

或任何其他方法,请参见How do I remove blank elements from an array?

否则,您将必须使用正则表达式 match 匹配子字符串,该正则表达式将首先匹配deilimiters,然后匹配任何不以delimiter文本开头的文本(也就是说,您需要构建{ {3}}):

arr = s.scan(/(?x)\*{2}|[*\n.]|(?:(?!\*{2})[^*\n.])+/)

请参见tempered greedy token

在这里

  • (?x)-一个自由行距/注释修饰符
  • \*{2}-**子字符串
  • |-或
  • [*\n.]-一个*,换行符LF或.
  • 的字符
  • |-或
  • (?:(?!\*{2})[^*\n.])+-不是+,LF或*.)的1个或多个([^*\n.])字符不会启动{{ 1}}子字符串。

答案 2 :(得分:1)

r = /
    [ ]+    # match one or more spaces
    |       # or
    (\*)    # match one asterisk in capture group 1
    [ ]*    # match zero or more spaces
    (?!\*)  # not to be followed by an asterisk (negative lookahead)
    |       # or
    (\n)    # match "\n" in capture group 2
    /x      # free-spacing regex definition mode

str = "Ayy ***lol* m8\nlol"

str.split r
  #=> ["Ayy", "**", "*", "lol", "*", "m8", "\n", "lol"]