仅限数字和特殊字符的正则表达式

时间:2015-08-17 16:45:50

标签: ruby regex

我想检查我的字符串是否只包含数字,空格和以下特殊字符:

[ ] , 

我在" How to check string contains special character in ruby":

中尝试了以下操作
special = "1234567890[], "
regex = /[#{special.gsub(/./){|char| "\\#{char}"}}]/ 
test1 = [1,2,[3,4],5].to_s
test2 = ["a",2,[3,4],5].to_s

运行这些时,它们都返回"失败":

puts "fail" if test1 =~ regex
puts "fail" if test2 =~ regex

有人可以为此提供帮助吗?

4 个答案:

答案 0 :(得分:3)

没有正则表达式的解决方案:

str = "123 [],"
# count all chars that are NOT 1-9, [] 
# the count should be zero
str.count("^0-9, []").zero? # => true

答案 1 :(得分:1)

试试这个

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 :(得分:0)

您可以使用

If wsInput.Name<>wsOutput.name and worksheets(wsInput).visible Then

请参阅demo(请注意,regex = /\A[\[\],\p{Zs}\p{N}]+\z/ \A已替换为\z^以进行演示,以匹配整行,而不是字符串)。

此外,还有IDEONE demo

正则表达式匹配:

  • $ - 字符串开头
  • \A - 一个或多个字符[\[\],\p{Zs}\p{N}]+[或逗号,空格(])或数字(\p{Zs} )。
  • \p{N} - 字符串结尾

为什么不\z如果我们使用替代方案,回溯步骤的数量会增加,而且很长的字符串最终会导致更快的灾难性回溯。换句话说,它会降低性能。

为什么不\A(\[|\]|,|\p{Zs}|\p{N})+\z / ^在Ruby中,$匹配行的开头,而不是整个字符串。与^相同,它匹配行的结尾,而不是字符串的结尾。

答案 3 :(得分:0)

不要这样做:

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会返回正确转义的字符串:

Regexp.escape(special)
# => "1234567890\\[\\],\\ "

但是等等,还有更多:

使用动态生成的正则表达式可能会有一些你需要警惕的陷阱,特别是当你试图将它们插入到字符串中时。考虑一下:

regex = Regexp.new(Regexp.escape(special)) # => /1234567890\[\],\ /
/^[#{regex}]+$/ # => /^[(?-mix:1234567890\[\],\ )]+$/

注意(?-mix:部分?这是一种正则表达方式,表示(...)中的所有内容都使用了自己的mix选项忽略模式告诉它的其他任何东西&#34;。这是你的模式中的一个漏洞真的难以调试,除非你知道它可以存在。您需要阅读Regexp文档以了解the options的含义,但这里有一个可以发生疯狂的例子:

(/^foo[#{regex}]+bar$/imx).to_s # => "(?mix:^foo[(?-mix:1234567890\\[\\],\\ )]+bar$)"

请注意,有两组不同的选项,其中内部集忽略了外部集的配置。这会导致疯狂。

相反,在插入前,使用source将正则表达式转回其源表示形式:

/^[#{regex}]+$/ # => /^[(?-mix:1234567890\[\],\ )]+$/

VS

/^[#{regex.source}]+$/ # => /^[1234567890\[\],\ ]+$/

此时,内插图案将与外部图案的选项相匹配,保持理智并按照您实际期望的方式进行。

在这一点上,这样的东西会起作用:

test1 = [1,2,[3,4],5].to_s # => "[1, 2, [3, 4], 5]"
test1[/^[#{Regexp.escape(special)}]+$/] # => "[1, 2, [3, 4], 5]"

或:

test1[/^[#{regex.source}]+$/] # => "[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

为了提高速度和极致,您应该使用https://stackoverflow.com/a/32058208/128421。它会在任何正则表达式周围运行:

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?更容易阅读和维护。

相关问题