Perl Regex:如何恰好匹配一个角色

时间:2013-04-19 02:12:59

标签: regex perl

我对正则表达式一般都很陌生,在准备参加秋季学期的Perl课程时,我想早点弄湿我的脚。我仍然围绕着他们,并做了非常基本的事情来了解匹配和替换是如何工作的。所以我写了一个简单的脚本来检查员工的身份证号码是否有效。我想出的简单要求是:

  1. 必须以9
  2. 开头
  3. 整数中只能有一个零
  4. 我不能为我的生活弄清楚如果它有多于零的情况如何使条件失败。我的代码如下所示:

    $s;
    print("Please enter your id number: ");
    $s = <STDIN>;
    
    if(($s =~ /^9/) && ($s =~ /0{1}/))
    {
        print("ID is valid\n");
    }
    else
    {
        print("ID not valid\n");
    }
    

    条件的第二部分($ s =〜/ 0 {1} /)我读作“只匹配一个零”但如果数字是包含多个零的东西,只要它们是无效的,它就不会起作用不重复(例如:90401返回有效,其中90091无效)。我知道这是可能的,但我已经尝试了很多没有解决方案的组合。正确方向的任何一点都是最有帮助的。

5 个答案:

答案 0 :(得分:4)

最有效的代码是拒绝最有可能发生的坏情况(包含非数字)的代码,然后是快速进行perl检查的情况(从9开始)然后是最终情况(不超过1)零)。

if ($s =~ m/[^0-9]/ || $s =~ m/^[^9]/ || ($s =~ s/0/0/g) > 1) {
print "Invalid\n";
}

快速单个正则表达式,如果ID有效则为true,但它仍然比我对无效输入的第一个解决方案慢,并且在有效输入上没有更快:

m/^9[1-9]*(0[1-9]*)?$/

这与正则表达式一样快,因为我认为可以在一次操作中完成工作。使用?:非捕获组似乎会更快,它应该,但在实际的perl实现中,它会慢大约15%。

答案 1 :(得分:2)

这个正则表达式应该这样做:

/^9[1-9]*0?[1-9]*$/

以9开头,任意数字1-9,可能为0,后跟任意数字1-9。

答案 2 :(得分:1)

if ($s =~ /^9[1-9]*0?[1-9]*$/)

或者您可以使用@{[$n =~ /0/g]}来计算“0”。

if (($s =~ /^9[0-9]+$/) && (@{[$s =~ /0/g]} <= 1))

答案 3 :(得分:1)

默认情况下,匹配运算符m //(或简称//)扫描字符串以查找与模式的第一个匹配项,然后退出。

  

我读的是“只匹配一个零”

它实际上是“正好匹配一次0”。

因此匹配运算符将扫描字符串“900009”,并在字符串中的位置1处找到一次0匹配,然后退出。匹配运算符也会找到匹配0正好2次,匹配0正好3次,并且匹配0正好4次在字符串中的位置1。

  

我不能为我的生活找出如果条件有多于零的情况如何使条件失败。&lt;

如何在字符串中找到0的所有匹配项,如果它超过1,那么拒绝该字符串?

use strict;   
use warnings;   
use 5.012;  

my @strings = (
    "90909",
    "909",
    "999",
);

for my $str (@strings) {
    my @matches = $str =~ /0/g;
    say scalar @matches;
}

--output:--
2
1
0

实际上有一种奇特的方法可以将计数排在一行:

my $count = () = $str =~ /0/g;

答案 4 :(得分:1)

在接受的答案中实际上有很多冗余。它不仅会计算所有零,还会花费不必要的时间来替换它们!?

以下没有那么多冗余,一旦找到两个零就会停止:

/^9[0-9]*\z/ && /^[^0]*+(?:0[^0]*+)?+\z/
   or die;