在Perl中,我该如何检查一个值是数字、字母还是字母数字混合的?

3

我有一个数组,其中的值是用户输入的,例如:

aa df rrr5 4323 54 hjy 10 gj @fgf %d

现在我想检查数组中的每个值,看它们是数字、字母(a-zA-Z)还是字母数字混合,并将它们保存在其他相应的数组中。
我已经完成了:
my @num;
my @char;
my @alphanum;

my $str =<>;
  my @temp = split(" ",$str);
        foreach (@temp)
           {
                print "input : $_ \n";
                if ($_ =~/^(\d+\.?\d*|\.\d+)$/)
                    {
                        push(@num,$_);
                    }
           }

这个可以运行。同样地,我想检查字母和字母数字的值

字母数字示例: fr43 6t$ $eed5 *jh


你接受的答案并不能产生你在问题中所要求的结果。具体来说,POSIX字符类[:alphanum:]不会匹配标点符号,这意味着6t$ $eed5 *jh将无法匹配。请查看下面我更新的答案。 - Robert S. Barnes
@Robert S. Barnes:是的,你说得对,我没有足够地关注我的需求,对此很抱歉。同时感谢你让我意识到这一点。 - dexter
5个回答

8
Perl支持POSIX字符类,因此您可以实际执行以下操作:
$string =~ /^[[:alpha:]]+$/;
$string =~ /^[[:alnum:]]+$/;

数字的定义不太清晰,但是Scalar::Util的looks_like_number函数可能会做你想要的事情。


1
检查字符串是否为单个字母或数字字符(可能带有后续的 \n)的问号。 - ysth

3
你所接受的答案并不能产生你在问题中所要求的结果。具体来说,POSIX字符类[:alphanum:]不会匹配标点符号,这意味着6t$ $eed5 *jh将不会被匹配。为了匹配标点符号,你需要将[:punct:]添加到字符类中。请参考正则表达式速查表
例如,如果你有一个包含以下内容的文件tokens.txt:

aa df rrr5 4323 54 hjy 10 gj @fgf %d fr43 6t$ $eed5 *jh

并运行此Perl脚本:
#!/usr/bin/perl -w
use warnings;
use diagnostics;
use strict;
use Scalar::Util qw( looks_like_number );


my $str =<>;
my @temp = split(" ",$str);

my @num = grep { looks_like_number($_) } @temp;
my @char = grep /^[[:alpha:]]+$/, @temp;
my @alphanum = grep /^[[:alnum:][:punct:]]+$/, @temp;

print "Numbers: " . join(' ', @num) . "\n";
print "Alpha: " . join(' ', @char) . "\n";
print "Alphanum: " . join(' ', @alphanum) . "\n";

就像这样:

cat tokens.txt | ./tokenize.pl

你会得到以下输出:

数字:4323 54 10
字母:aa df hjy gj
字母数字混合:aa df rrr5 4323 54 hjy 10 gj @fgf %d fr43 6t$ $eed5 *jh

然而,从你的问题来看,似乎你不想匹配所有标点符号,例如@和%,而是只想匹配特定的标点符号,如$和*。
如果是这种情况,那么你只需要将Alphanum匹配改为:
my @alphanum = grep /^[[:alnum:]\$\*]+$/, @temp;

然后您将获得所需的输出:

数字:4323 54 10
字母:aa df hjy gj
数字和字母混合:aa df rrr5 4323 54 hjy 10 gj fr43 6t$ $eed5 *jh


1

如果要将输入分离成数组,可以使用类似以下的方法,这样可以轻松添加或更改匹配项。

my $input = 'aa df rrr5 4323 54 hjy 10 gj @fgf %d';
my %tests = ( 
    num   => '\d+',
    alpha => '[[:alpha:]]+', 
    alnum => '[[:alnum:]]+' 
);

my %res;
for my $t (keys %tests) {
    for (split(' ', $input)) {
        push(@{ $res{$t} }, $_) if (/^$tests{$t}$/i);
    }
}

0
如果你想识别所有有效的数字(科学计数法/固定计数法/...),可以让 Perl 这样做:
sub test_num {
    no warnings "all";
    $b = "$_[0]"; 
    $a = $b + 0; 
    return ($a eq $b);
}
push(@num, $tmp) if (test_num($tmp));

代码行 $b = "$_[0]"; 的原因是,否则原始变量 $tmp 会在 test_num 函数内部被带入数字上下文中 - 这是一种不必要的副作用。


0

字母表:

 /^[a-z]+$/i

大多数人所说的字母数字:

 /^[a-z0-9]+$/i

等等:

注意:字母数字混合,例如 fr43 6t$ $eed5 *jh

我不太理解这个,但根据您下面的评论和上面的引用,您所说的字母数字混合可能可以通过以下方式实现

 /^[[:graph:]]+$/

这匹配任何可打印的ASCII字符,但不包括空格。

希望这解决了你的问题。


@Kinopiko:这个注释是为了说明特殊字符是包含在字母数字中而不是字母表中。 - dexter
我理解为任何非数字或字母的字符都被归类为字母数字字符,不管这些字符是什么。 - ysth

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