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
    -字符串的开头
  • [\[\]、\p{Zs}\p{N}+
    -1个或多个字符,它们要么是
    [
    ]
    或逗号,要么是空格(
    \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