0

总的来说,我是正则表达式的新手,在准备秋季学期的 Perl 课程时,我想早点弄湿自己的脚。我仍然围绕着它们,做一些非常基本的事情来了解匹配和替换是如何工作的。所以我写了一个简单的脚本来检查员工的身份证号码是否有效。我提出的简单要求是:

  1. 必须从 9 开始
  2. 整数中只能有一个零

如果条件超过一个零,我终生无法弄清楚如何使条件失败。我的代码如下所示:

$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 无效)。我知道这已经成为可能,但我尝试了很多没有解决方案的组合。朝着正确方向的任何一点都是最有帮助的。

4

5 回答 5

4

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

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

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

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

这是一个正则表达式的速度,我认为可以在一个操作中完成这项工作。使用 ?: 非捕获组似乎会更快,而且应该,但在 perl 的实际实现中,它会慢约 15%。

于 2013-04-19T02:42:54.790 回答
2

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

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

从 9 开始,1-9 的任意数字,可能是 0,然后是 1-9 的任意数字。

于 2013-04-19T02:20:38.670 回答
1

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

我正在阅读,“只匹配一个零”

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

因此,匹配操作符将扫描字符串“900009”,并在字符串中的位置 1 处恰好一次找到匹配 0 的匹配项,然后退出。匹配运算符还将在字符串中的位置 1 处找到 0 恰好 2 次的匹配,以及 0 恰好 3 次的匹配,以及 0 恰好 4 次的匹配。

如果条件超过一个零,我一生都无法弄清楚如何使条件失败。<

如何在字符串中找到 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;
于 2013-04-19T02:35:17.673 回答
1
if ($s =~ /^9[1-9]*0?[1-9]*$/)

或者你可以@{[$n =~ /0/g]}用来数“0”。

if (($s =~ /^9[0-9]+$/) && (@{[$s =~ /0/g]} <= 1))
于 2013-04-19T02:28:57.257 回答
1

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

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

/^9[0-9]*\z/ && /^[^0]*+(?:0[^0]*+)?+\z/
   or die;
于 2013-04-19T03:34:18.760 回答