如果字符不属于数组,如何指定匹配应该发生?
How to I specify that a match should occur if a character does not belong to an array?
我在正则表达式中指定 "the next character should not be from this group of characters" 时遇到问题。我有
TOKENS = [":", ".", "'"]
"01:39\t" =~ /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
#=> nil
因为 "\t"
不是我的 TOKENS
数组的一部分,我认为上面应该匹配,但它不匹配。如何调整我的正则表达式,特别是这部分
^#{Regexp.union(TOKENS)}
说这个字符不应该是这个数组的一部分?
正则表达式的 "not" 部分需要括号。
>> TOKENS = [":", ".", "'"]
>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
>> "01:39\t" =~ regex
#=> nil
但是:
>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d[^#{Regexp.union(TOKENS)}]/
# Add brackets here^ and here^
>> "01:39\t" =~ regex
#=> 0
您的 /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
模式最终会像
/(?-mix:\b0\d[(?-mix::|\.|')]\d\d^(?-mix::|\.|'))/
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
这里,正则表达式对象是一个修饰符组,禁用了多行、不区分大小写和自由间距模式。最后一个 ^
是行锚点的开始,它单独破坏了整个正则表达式,将其变成一个永远不匹配任何字符串的模式。
用 [...]
字符 class 括号包裹 #{Regexp.union(TOKENS)}
是不够的,您需要使用 .source
属性 摆脱 (?-mix:...)
因为你不想否定 m
、i
、x
等 但是,你不能使用 Regexp.union
,因为它会添加 |
字符,并在字符 class 内,它被视为文字字符(因此,你也会否定管道)。
您应该使用 TOKENS.join().gsub(/[\]\[\^\-]/, '\\\&')
定义分隔符序列以转义所有应该在正则表达式字符 class 内转义的字符,然后放在字符 class 方括号之间。
TOKENS = [":", ".", "'", "]"]
sep_rx = TOKENS.join().gsub(/[\]\[\^\-]/, '\\\&')
puts sep_rx
# => :.'\]
rx = /\b0\d[#{sep_rx}]\d\d[^#{sep_rx}]/
puts rx.source
# => \b0\d[:.'\]]\d\d[^:.'\]]
puts "01:39\t" =~ rx
# => 0
注意 .gsub(/[\]\[\^\-]/, '\\\&')
匹配 ]
、[
、^
、\
和 -
并在它们前面添加一个反斜杠. '\\\&'
中的前 4 个反斜杠定义替换模式中的文字反斜杠,\&
代表整个匹配项
我在正则表达式中指定 "the next character should not be from this group of characters" 时遇到问题。我有
TOKENS = [":", ".", "'"]
"01:39\t" =~ /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
#=> nil
因为 "\t"
不是我的 TOKENS
数组的一部分,我认为上面应该匹配,但它不匹配。如何调整我的正则表达式,特别是这部分
^#{Regexp.union(TOKENS)}
说这个字符不应该是这个数组的一部分?
正则表达式的 "not" 部分需要括号。
>> TOKENS = [":", ".", "'"]
>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
>> "01:39\t" =~ regex
#=> nil
但是:
>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d[^#{Regexp.union(TOKENS)}]/
# Add brackets here^ and here^
>> "01:39\t" =~ regex
#=> 0
您的 /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
模式最终会像
/(?-mix:\b0\d[(?-mix::|\.|')]\d\d^(?-mix::|\.|'))/
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
这里,正则表达式对象是一个修饰符组,禁用了多行、不区分大小写和自由间距模式。最后一个 ^
是行锚点的开始,它单独破坏了整个正则表达式,将其变成一个永远不匹配任何字符串的模式。
用 [...]
字符 class 括号包裹 #{Regexp.union(TOKENS)}
是不够的,您需要使用 .source
属性 摆脱 (?-mix:...)
因为你不想否定 m
、i
、x
等 但是,你不能使用 Regexp.union
,因为它会添加 |
字符,并在字符 class 内,它被视为文字字符(因此,你也会否定管道)。
您应该使用 TOKENS.join().gsub(/[\]\[\^\-]/, '\\\&')
定义分隔符序列以转义所有应该在正则表达式字符 class 内转义的字符,然后放在字符 class 方括号之间。
TOKENS = [":", ".", "'", "]"]
sep_rx = TOKENS.join().gsub(/[\]\[\^\-]/, '\\\&')
puts sep_rx
# => :.'\]
rx = /\b0\d[#{sep_rx}]\d\d[^#{sep_rx}]/
puts rx.source
# => \b0\d[:.'\]]\d\d[^:.'\]]
puts "01:39\t" =~ rx
# => 0
注意 .gsub(/[\]\[\^\-]/, '\\\&')
匹配 ]
、[
、^
、\
和 -
并在它们前面添加一个反斜杠. '\\\&'
中的前 4 个反斜杠定义替换模式中的文字反斜杠,\&
代表整个匹配项