2

如何分隔字符串中的不同字符集?例如,如果我有这些字符集:

[a-z]
[A-Z]
[0-9]
[\s]
{everything else}

这个输入:

thisISaTEST***1234pie

然后我想分隔不同的字符集,例如,如果我使用换行符作为分隔符:

this
IS
a
TEST
***
1234
pie

我已经尝试过这个正则表达式,具有积极的前瞻性:

'thisISaTEST***1234pie'.gsub(/(?=[a-z]+|[A-Z]+|[0-9]+|[\s]+)/, "\n")

但显然+s 并没有贪心,因为我得到:

t
h
# (snip)...
S
T***
1
# (snip)...
e

我剪掉了不相关的部分,但正如你所看到的,每个字符都算作它自己的字符集,除了{everything else}字符集。

我怎样才能做到这一点?它不一定必须是正则表达式。将它们拆分成一个数组也可以。

4

4 回答 4

4

困难的部分是匹配与正则表达式其余部分不匹配的任何内容。忘记这一点,想想一种可以将不匹配的部分与匹配的部分混合在一起的方法。

"thisISaTEST***1234pie"
.split(/([a-z]+|[A-Z]+|\d+|\s+)/).reject(&:empty?)
# => ["this", "IS", "a", "TEST", "***", "1234", "pie"]
于 2013-08-27T00:07:24.533 回答
1

在 ASCII 字符集中,除了字母数字和空格之外,还有 32 个“标点”字符,它们与属性构造相匹配\p{punct}

要将字符串拆分为单个类别的序列,您可以编写

str = 'thisISaTEST***1234pie'
p str.scan(/\G(?:[a-z]+|[A-Z]+|\d+|\s+|[\p{punct}]+)/)

输出

["this", "IS", "a", "TEST", "***", "1234", "pie"]

或者,如果您的字符串包含 ASCII 集之外的字符,您可以根据属性编写整个内容,如下所示

p str.scan(/\G(?:\p{lower}+|\p{upper}+|\p{digit}+|\p{space}|[^\p{alnum}\p{space}]+)/)
于 2013-08-27T01:02:42.267 回答
0

这里有两个解决方案。

String#scan使用正则表达式

str = "thisISa\n TEST*$*1234pie"
r = /[a-z]+|[A-Z]+|\d+|\s+|[^a-zA-Z\d\s]+/
str.scan r
  #=> ["this", "IS", "a", "\n ", "TEST", "*$*", "1234", "pie"]

因为在该字符类^的开头匹配除字母(小写和大写)、数字和空格以外的任何字符。[^a-zA-Z\d\s]

使用Enumerable#slice_when 1

首先,一个辅助方法:

def type(c)
  case c
  when /[a-z]/ then 0
  when /[A-Z]/ then 1
  when /\d/    then 2
  when /\s/    then 3
  else              4
  end
end

例如,

type "f"   #=> 0
type "P"   #=> 1
type "3"   #=> 2
type "\n"  #=> 3
type "*"   #=> 4    

然后

str.each_char.slice_when { |c1,c2| type(c1) != type(c2) }.map(&:join)
  #=> ["this", "IS", "a", "TEST", "***", "1234", "pie"]

1.slich_when在Ruby v2.4中首次亮相。

于 2020-11-25T09:12:20.840 回答
-1

非单词、非空格字符可以用 覆盖[^\w\s],所以:

"thisISaTEST***1234pie".scan /[a-z]+|[A-Z]+|\d+|\s+|[^\w\s]+/
#=> ["this", "IS", "a", "TEST", "***", "1234", "pie"]
于 2013-08-27T01:34:41.760 回答