Ruby 如何拆分字符串而不在数组中插入空字符串
假设存在匹配项,使用正则表达式从字符串中拆分字符时遇到问题 假设下一个字符是一个或多个数字,后跟可选的空格字符,后跟我拥有的数组中的一个字符串,我想从字符串的第一部分拆分出一个“m”或“f”字符 我试过:Ruby 如何拆分字符串而不在数组中插入空字符串,ruby,regex,split,Ruby,Regex,Split,假设存在匹配项,使用正则表达式从字符串中拆分字符时遇到问题 假设下一个字符是一个或多个数字,后跟可选的空格字符,后跟我拥有的数组中的一个字符串,我想从字符串的第一部分拆分出一个“m”或“f”字符 我试过: 2.4.0 :006 > MY_SEPARATOR_TOKENS = ["-", " to "] => ["-", " to "] 2.4.0 :008 > str = "M14-19" => "M14-19" 2.4.0 :011 > str.split
2.4.0 :006 > MY_SEPARATOR_TOKENS = ["-", " to "]
=> ["-", " to "]
2.4.0 :008 > str = "M14-19"
=> "M14-19"
2.4.0 :011 > str.split(/^(m|f)\d+[[:space:]]*#{Regexp.union(MY_SEPARATOR_TOKENS)}/i)
=> ["", "M", "19"]
请注意数组开头的无关“”元素,还请注意最后一个表达式仅为“19”,而我希望字符串中的所有内容(“14-19”)
如何调整正则表达式,以便只有表达式中被拆分的部分在数组中结束?如果获得匹配项,则空元素将始终存在,因为捕获的部分显示在字符串的开头,而字符串开头和匹配项之间的字符串将添加到结果数组中,无论是空字符串还是非空字符串。获得匹配后,可以使用
shift
/删除它,也可以使用删除所有空数组元素。拒绝{c | c.empty?}
(请参阅)
然后,14-
被\d+[:space:]…
模式部分吃掉(消耗)-将其放入一个(?=…)
前瞻中,该前瞻将只检查模式匹配,但不会消耗字符
使用类似
MY_SEPARATOR_TOKENS = ["-", " to "]
s = "M14-19"
puts s.split(/^(m|f)(?=\d+[[:space:]]*#{Regexp.union(MY_SEPARATOR_TOKENS)})/i).drop(1)
#=> ["M", "14-19"]
参见在Ruby中从正则表达式提取字符时,我发现匹配
更加优雅:
string = "M14-19"
string.match(/\A(?<m>[M|F])(?<digits>\d{2}(-| to )\d{2})/)[1, 2]
=> ["M", "14-19"]
# also can extract the symbols from match
extract_string = string.match(/\A(?<m>[M|F])(?<digits>\d{2}(-| to )\d{2})/)
[[extract_string[:m], extract_string[:digits]]
=> ["M", "14-19"]
string = 'M14 to 14'
extract_string = string.match(/\A(?<m>[M|F])(?<digits>\d{2}(-| to )\d{2})/)[1, 2]
=> ["M", "14 to 14"]
string=“M14-19”
string.match(/\A(?[M | F])(?\d{2}(-to)\d{2})/)[1,2]
=>[“M”,“14-19”]
#还可以从匹配中提取符号
extract_string=string.match(/\A(?[M | F])(?\d{2}(-to)\d{2})/)
[[extract_string[:m],extract_string[:digits]]
=>[“M”,“14-19”]
字符串='M14到14'
extract_string=string.match(/\A(?[M|F])(?\d{2}(-to)\d{2})/)[1,2]
=>[“M”,“14至14”]
您的代码中正在酝酿一个bug。请不要养成这样做的习惯:
#{Regexp.union(MY_SEPARATOR_TOKENS)}
你给自己设置了一个很难调试的问题
下面是正在发生的事情:
regex = Regexp.union(%w(a b)) # => /a|b/
/#{regex}/ # => /(?-mix:a|b)/
/#{regex.source}/ # => /a|b/
/(?-mix:a | b)/
是一个嵌入式子模式,它有一组regex标志m
、i
和x
,它们独立于周围模式的设置
考虑这种情况:
'CAT'[/#{regex}/i] # => nil
我们希望正则表达式i
标志会匹配,因为它忽略大小写,但子表达式仍然只允许小写,导致匹配失败
使用裸(a | b)
或添加源代码
成功,因为内部表达式获取主表达式的i
:
'CAT'[/(a|b)/i] # => "A"
'CAT'[/#{regex.source}/i] # => "A"
有关此问题的更多讨论,请参见“”
TOKENS = ["-", " to "]
r = /
(?<=\A[mMfF]) # match the beginning of the string and then one
# of the 4 characters in a positive lookbehind
(?= # begin positive lookahead
\d+ # match one or more digits
[[:space:]]* # match zero or more spaces
(?:#{TOKENS.join('|')}) # match one of the tokens
) # close the positive lookahead
/x # free-spacing regex definition mode
当在r
上拆分时,您在两个字符之间进行拆分(在正向向后看和正向向前看之间),因此不会使用任何字符
"M14-19".split r
#=> ["M", "14-19"]
"M14 to 19".split r
#=> ["M", "14 to 19"]
"M14 To 19".split r
#=> ["M14 To 19"]
如果希望在最后一个示例中返回[“M”,“14到19”]
,请将[mMfF]
更改为[mf]
,将/x
更改为/xi
我不知道您所说的“拆分”或“字符串的第一部分”是什么意思。如果原始字符串是str
您希望返回str[1..-1]
当str[0]=~/[mf]/i
和其他两个条件都满足时?如果不匹配,str
将返回什么?你能用drop 1
替换reject
,这将更具描述性吗?@CarySwoveland:我修改了代码示例。.drop(1)
只是去除第一个数组元素的另一种方法,但在大多数情况下,删除所有空元素是预期的行为。行(?:#{TOKENS.join('.|')}
以前是{Regexp.union(TOKENS)}
。我在阅读了@thetinman的答案后更改了它,这澄清了我对它的理解及其潜在缺陷。
"M14-19".split r
#=> ["M", "14-19"]
"M14 to 19".split r
#=> ["M", "14 to 19"]
"M14 To 19".split r
#=> ["M14 To 19"]