Ruby 仅用于数字和特殊字符的正则表达式
我想检查我的字符串是否只包含数字、空格和以下特殊字符:Ruby 仅用于数字和特殊字符的正则表达式,ruby,regex,Ruby,Regex,我想检查我的字符串是否只包含数字、空格和以下特殊字符: [ ] , 我从“”尝试了以下操作: 运行这些时,它们都返回“fail”: 有人能帮忙吗?试试这个 your_string.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) 我试过这个 2.2.2 :033 > "123a1231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) => nil 2.2.2 :034 >
[ ] ,
我从“”尝试了以下操作:
运行这些时,它们都返回“fail”:
有人能帮忙吗?试试这个
your_string.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
我试过这个
2.2.2 :033 > "123a1231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
=> nil
2.2.2 :034 > "1231231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
=> #<MatchData "1231231,2]" 1:"]">
2.2.2 :035 > "12.31231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
=> nil
2.2.2 :036 > "aa1231231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
=> nil
2.2.2 :037 > "12[31231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/)
=> #<MatchData "12[31231,2]" 1:"]">
2.2.2 :038 > "12[31231,2]".match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/).to_s
=> "12[31231,2]"
2.2.2 :039 >
2.2.2:033>“123a1231,2]”。匹配(/^([[:digit:].\].\].[[:space:].\[\124;\,)*$/)
=>零
2.2.2:034>“1231231,2]”。匹配(/^([:数字:].\].\].\[:空格:].\[\\.\,)*$/)
=> #
2.2.2:035>“12.31231,2]”。匹配(/^([[:digit:].\].\].[:space:].\[\.\,)*$/)
=>零
2.2.2:036>“aa1231231,2]”。匹配(/^([[:数字:].\].\].[[:空格:].\[.\,)*$/)
=>零
2.2.2:037>“12[31231,2]”。匹配(/^([[:digit:].\].\].[:space:].\[\.\,)*$/)
=> #
2.2.2:038>“12[31231,2]”。匹配(/^([[:数字:].\].\].[:空格:].\[.\\.\,)*$/)。到
=> "12[31231,2]"
2.2.2 :039 >
您可以使用
regex = /\A[\[\],\p{Zs}\p{N}]+\z/
请参阅(请注意,\A
和\z
被替换为^
和$
,用于演示,以匹配整行,而不是字符串)
还有,这里有一个例子
正则表达式匹配:
-字符串的开头\A
-1个或多个字符,它们要么是[\[\]、\p{Zs}\p{N}+
或[
或逗号,要么是空格(]
)或数字(\p{Zs}
)\p{N}
-字符串结尾\z
\A(\[\124;\]\ 124;\ p{Zs}\p{N})+\z
?如果我们使用替代方案,回溯步骤的数量会增加,并且非常长的字符串会更快地结束catatrophic回溯。换句话说,它会降低性能
为什么不^
/$
?在Ruby中,^
在一行的开头匹配,而不是整个字符串。与$
相同,它匹配行的结尾,而不是字符串的结尾。不要这样做:
special = "1234567890[], "
regex = /[#{special.gsub(/./){|char| "\\#{char}"}}]/
# => /[\1\2\3\4\5\6\7\8\9\0\[\]\,\ ]/
使用可用的工具:
regex = Regexp.new(Regexp.escape(special))
# => /1234567890\[\],\ /
返回正确转义的字符串:
Regexp.escape(special)
# => "1234567890\\[\\],\\ "
但是等等,还有更多:
<>使用动态生成的正则表达式可以有一些需要注意的问题,尤其是当你试图将它们插入字符串时。
regex = Regexp.new(Regexp.escape(special)) # => /1234567890\[\],\ /
/^[#{regex}]+$/ # => /^[(?-mix:1234567890\[\],\ )]+$/
注意(?-mix:
部分?这是正则表达式的一种表达方式,表示“在(…)
中的所有内容都使用自己的m
、i
和x
选项,因此忽略模式告诉它的任何其他内容”。这是模式中的一个漏洞,除非您意识到它可能存在,否则很难调试。您需要阅读Regexp文档以了解其含义,但下面是一个可能发生疯狂的示例:
(/^foo[#{regex}]+bar$/imx).to_s # => "(?mix:^foo[(?-mix:1234567890\\[\\],\\ )]+bar$)"
请注意,有两组不同的选项,其中内部选项集忽略外部选项集的配置。这会导致疯狂
相反,在插入正则表达式之前,使用将其转换回其源表示形式:
/^[#{regex}]+$/ # => /^[(?-mix:1234567890\[\],\ )]+$/
vs:
在这一点上,内部插值模式将匹配外部模式的选项,保持您的理智,并执行您实际期望的操作
在这一点上,类似的方法将起作用:
test1 = [1,2,[3,4],5].to_s # => "[1, 2, [3, 4], 5]"
test1[/^[#{Regexp.escape(special)}]+$/] # => "[1, 2, [3, 4], 5]"
或:
但我会用一些更简单的方法来处理它:
test1[/^[\d\[\], ]+$/] # => "[1, 2, [3, 4], 5]"
或者将设置反转,使其更加简单:
test1[/[^\d\[\], ]/] # => nil
test2 = ["a",2,[3,4],5].to_s
test2[/[^\d\[\], ]/] # => "\""
或者否定它来测试我是否拥有我想要的所有字符:
!test1[/[^\d\[\], ]/] # => true
!test2[/[^\d\[\], ]/] # => false
为了速度和终极的简单性,您应该使用它。它将围绕任何正则表达式运行:
require 'fruity'
special = "1234567890[], "
test1 = [1,2,[3,4],5].to_s # => "[1, 2, [3, 4], 5]"
compare {
steenslag { test1.count("^0-9, []").zero? }
ttm { !test1[/[^\d\[\], ]/] }
Horacio_Branciforte { test1.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) }
}
# >> Running each test 4096 times. Test will take about 1 second.
# >> steenslag is faster than ttm by 19.999999999999996% ± 10.0%
# >> ttm is faster than Horacio_Branciforte by 3x ± 0.1 (results differ: true vs [1, 2, [3, 4], 5])
当然,正确地锚定可以弥补这一差异:
compare {
steenslag { test1.count("^0-9, []").zero? }
ttm { !test1[/[^\d\[\], ]/] }
ttm1 { !test1[/^[^\d\[\], ]/] }
ttm2 { !test1[/[^\d\[\], ]$/] }
# stribizhev { test1.match(/\A[\[\],\p{Zs}\p{N}]+\z/) }
Horacio_Branciforte { test1.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) }
}
# >> Running each test 4096 times. Test will take about 1 second.
# >> steenslag is similar to ttm2
# >> ttm2 is similar to ttm
# >> ttm is similar to ttm1
# >> ttm1 is faster than Horacio_Branciforte by 2x ± 1.0 (results differ: true vs [1, 2, [3, 4], 5])
但是,
test1.count(“^0-9,[]).zero?
更易于阅读和维护。不使用regexp的解决方案:
str = "123 [],"
# count all chars that are NOT 1-9, []
# the count should be zero
str.count("^0-9, []").zero? # => true
^
是字符串的开头,$
是字符串的结尾。字符类用[]定义
,你可以在里面放置不同的字符。如果这些字符有特殊的含义,你可以将它们转义,这样它们将与反斜杠完全匹配。在字符类之后使用*
,你可以指定它重复0次或更多次。试试看。你的意思是/[^\d\s\[\]\,]/
它只是说*不是数字,不是空格,不是[(字面意思),不是](字面意思)和不,(逗号)`如果有任何内容与此匹配,那么它将包含除这些字符以外的内容。我觉得在正则表达式方面可能存在更多的问题或缺乏理解。请提供建议。还要注意,to_s
可能会添加反斜杠以转义字符串,即使该字符串是一个数字,例如[“1”、“2”、“3”]。to#s=>“[\“1\”,\”2\“,\“3\”]“
(由于反斜杠和双引号,这将使正则表达式失败)/[^\d\s\[\]\,]/
不正确。\s
的意思不仅仅是一个空格,它是“空白”又名/[\t\r\n\f]/
。此外,不必在集合中转义逗号。可以用于测试正则表达式。这是最好的方法。它将围绕任何基于正则表达式的解决方案运行循环。锚定的解决方案除外。:-)这将导致无效的字符属性名{Zs}:/\a[\],a[\],p{Zs}\p{N}+\z/
看到了吗?它没有这样说(Ruby 2.1).Ruby对此表示不满。如果Ruby不编译它,无论演示是否喜欢都没有帮助。我会将您的添加到基准中,但已注释掉。请尝试复制基准并启用它。
!test1[/[^\d\[\], ]/] # => true
!test2[/[^\d\[\], ]/] # => false
require 'fruity'
special = "1234567890[], "
test1 = [1,2,[3,4],5].to_s # => "[1, 2, [3, 4], 5]"
compare {
steenslag { test1.count("^0-9, []").zero? }
ttm { !test1[/[^\d\[\], ]/] }
Horacio_Branciforte { test1.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) }
}
# >> Running each test 4096 times. Test will take about 1 second.
# >> steenslag is faster than ttm by 19.999999999999996% ± 10.0%
# >> ttm is faster than Horacio_Branciforte by 3x ± 0.1 (results differ: true vs [1, 2, [3, 4], 5])
compare {
steenslag { test1.count("^0-9, []").zero? }
ttm { !test1[/[^\d\[\], ]/] }
ttm1 { !test1[/^[^\d\[\], ]/] }
ttm2 { !test1[/[^\d\[\], ]$/] }
# stribizhev { test1.match(/\A[\[\],\p{Zs}\p{N}]+\z/) }
Horacio_Branciforte { test1.match(/^([[:digit:]]|\]|[[:space:]]|\[|\,)*$/) }
}
# >> Running each test 4096 times. Test will take about 1 second.
# >> steenslag is similar to ttm2
# >> ttm2 is similar to ttm
# >> ttm is similar to ttm1
# >> ttm1 is faster than Horacio_Branciforte by 2x ± 1.0 (results differ: true vs [1, 2, [3, 4], 5])
str = "123 [],"
# count all chars that are NOT 1-9, []
# the count should be zero
str.count("^0-9, []").zero? # => true