Ruby判断一个字符串是否只包含数字

3

我正在尝试创建一个方法,要求用户创建一个像银行账户PIN一样的PIN号码。它只能是4个数字长度,并且输入的每个字符都必须是数字。我发现当我使用这段代码时:

puts "Please give us a 4 digit pin number for your account:"
@response = gets.chomp 

unless @response.to_i.is_a?(Integer) && @response.to_str.length == 4
    puts "Your response must be 4 numbers in length."
    create_pin
else
    @pin = @response.to_i
    puts "Your pin has been set."
end

我希望它能按照我的偏好工作,因为.to_i方法会将'2134a'转换为2134。此外,如果字符串中没有整数,则记录值为0,而我需要的是false。

使用Ruby测试字符串是否基本上是整数?

我找到了一篇非常有用的文章,但由于正则表达式的原因,在线程中变得非常复杂。这篇文章也被关闭,因为创建者不够明确:

在Ruby中检查字符串是否仅包含正数

所以我尝试清楚地说明,我正在尝试限制用户输入,使他们只能输入0到9的数字。像10^3这样的数学方程需要失败,负数如-1234也需要失败,我试图将它们限制在四位数字以内,就像任何密码一样。到目前为止,我完全被卡住了,还没有看到一种不包含大量正则表达式的方法。

也许我可以检查字符串中是否包含不可接受的字符列表。
提前感谢您。
为了更好地表达并纠正我在第二段中写错的错误而进行了编辑。

4
这是一个简单的正则表达式。个人建议您花更多时间尝试弄清楚,或者向我们展示您所尝试过的内容。这比这更容易,并且很容易搜索到。 - Dave Newton
说实话,我不知道如何使用正则表达式。我想知道是否有像数字一样的特定方法(它没有起作用),但我想我迟早都得学习正则表达式。此外,我从来不知道我发布的代码是太多还是太少。我应该保持主题,但我从来不知道什么是主题,因为我的许多错误只是语法相关的。 - Mark H Jr
它将值记录为nil,而我需要它为false。 只是澄清一下,在Ruby中,nilfalse实际上是唯一的false。你的问题不在于nil,而是以非数字字符开头的字符串在调用to_i时会返回0。你正在说将此字符串转换为Integer,然后询问这是否是一个Integer。答案显然是当然是,因为你刚刚把它变成了一个整数。 - engineersmnky
2
正则表达式技能对于任何开发人员都是必备的。 - Dave Newton
所以我注意到了。wvandaal和hbejgel都向我推荐了Rubular。对于初学者来说,这似乎是一个很好的资源。此外,engineersmnky,你是正确的,我想打的是0而不是nil。当所有只使用字母的引脚实际上通过并保存为0时,我发现了这个问题。我会编辑以修复它。 - Mark H Jr
我发现http://www.regular-expressions.info/非常有帮助。此外,虽然密集,但[文档](http://www.ruby-doc.org/core-1.9.3/Regexp.html)也很好阅读。另外,我认为[Why's Poignant Guide](http://www.rubyinside.com/media/poignant-guide.pdf)中的正则表达式部分不错,但并不是每个人都喜欢那本书。 - Reinstate Monica -- notmaynard
4个回答

8

试试这个:

def valid_pin?(pin)
  /^\d{4}$/ === pin
end

基本上,这段话的意思是:
  1. /^d{4}$/ 是一个正则表达式,你可以看到它被包含在 / / 中间,中间有一个模式。
  2. ^$ 字符分别表示字符串的开头和结尾。基本上,它确保了只有四个连续数字的字符串才会被接受,而其他以数字之外的字符开头或结尾的字符串(如 "a1234""5678b")将不被接受。
  3. \d 是表示数字的正则表达式字符。当跟随着 {4} 时,这意味着要查找恰好有 4 个数字的字符串。Ruby 还允许您使用这种符号来指定最小值 {3,} 或范围 {3,6}
  4. === 方法(正如@iamnotmaynard所正确提到的),有时被称为“threequals”运算符,根据正则表达式是否匹配给定的字符串返回一个布尔值(truefalse)。
在您的代码中的上下文中:
puts "Please give us a 4 digit pin number for your account:"
@response = gets.chomp 

unless valid_pin?(@response)
  puts "Your response must be 4 numbers in length."
  create_pin
else
  @pin = @response.to_i
  puts "Your pin has been set."
end

如果你想尝试学习正则表达式(通常称为 RegExes),我鼓励你在这个很棒的网站上玩耍:Rubular,它有一个通用关键字列表和 RegEx 沙盒,可以帮助你测试你的创作。

3
这是正确的正则表达式。如果您使用[Regexp#===](http://www.ruby-doc.org/core-1.9.3/Regexp.html#method-i-3D-3D-3D),则可以简化命令并避免稍微有些欺骗性的“!!”(因为它返回布尔值):`/^\d{4}$/ === "1234" => true` - Reinstate Monica -- notmaynard

0
以下代码可以正常工作:
puts "Please give us a 4 digit pin number for your account:"
@response = gets.chomp 

unless @response.match(/\d{4}/) && @response.length == 4
  puts "Your response must be 4 numbers in length."
  create_pin
else
  @pin = @response.to_i
  puts "Your pin has been set."
end

0
这可以使用正则表达式在几行代码中完成。以下类似的代码可以实现它。
if @response =~ /^\d{4}$/
   @pin = @response
else
   puts "Your pin must be 4 numbers in length."
   create_pin
end

在正则表达式中,'^'和'$'分别表示字符串的开头和结尾。添加这些保证您不会在寻找的4个数字之前或之后有垃圾。因此,您可以避免像“1234a”这样的答案。
'\d{4}'将匹配4个连续的数字0-9。
因此,您已经将用户限制为仅响应类似于“3421”,“9843”等的内容。

0

你应该尝试使用正则表达式:

unless /[0-9]{4}/.match(@response).to_s.length == 4 && @response.length == 4 
    puts "Your response must be 4 numbers in length."
    create_pin
else
    @pin = /[0-9]{4}/.match(@response).to_s.to_i
    puts "Your pin has been set."
end

你可以在这个网站上玩弄正则表达式:http://rubular.com/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接