免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5925 | 回复: 19
打印 上一主题 下一主题

哪位朋友有检查汉字数字合法的正则表达式 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-20 23:29 |只看该作者 |倒序浏览
哪位朋友有检查汉字数字合法的正则表达式?谢谢!
五十九万三千一百
二百零四万
一千零五十万零四十
七千万五千
二亿二千万
十三亿一千万
四十九点五八
六又七分之一
百分之九十四点五

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
2 [报告]
发表于 2016-07-21 00:13 |只看该作者
本帖最后由 sunzhiguolu 于 2016-07-21 00:14 编辑

比如说非法的汉子数字 常见的组合形式有哪些? 希望进行哪些校验?

论坛徽章:
0
3 [报告]
发表于 2016-07-21 01:01 |只看该作者
回复 2# sunzhiguolu

我1楼列出的都是合法的汉字数字,也就是小学数学课程教的内容。
不符合小学数学课程教的就是非法的。

四十五[三]万三千一百七十[百]五点六八  #如果一个串内存在[]中的汉字数字,则肯定非法,也就是:四十五三万三千一百七十百五点六八


   

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
4 [报告]
发表于 2016-07-21 11:06 |只看该作者
本帖最后由 sunzhiguolu 于 2016-07-21 12:15 编辑

我感觉, 对于汉子数字的验证 使用递进排除的方法应该能够将非法的汉子排除掉
比如: 上面这个汉子数字:

  1. use strict;
  2. use warnings;
  3. use utf8;

  4. binmode (STDOUT, ":utf8");
  5. my $r_num = "一二三四五六七八九零";
  6. my $str = "四十五[三]万三千一百七十[百]五点六八";
  7. if ($str =~ /[^${r_num}十百千万]/){
  8.     print "No.1 Invalid data:<$str>\n";
  9. }

  10. $str = "四十五三万三千一百七十百五点六八";    # 这里的匹配不是很严谨, 由于 “点” 的存在
  11. if ($str =~ /[$r_num][$r_num]/){
  12.     print "No.2 Invalid data:<$str>\n";
  13. }

  14. $str = "四十三万三千一百七十百五";
  15. if ($str !~ /[$r_num][$r_num]/){
  16.     print "No.3 valid data:<$str>\n";
  17. }
复制代码

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
5 [报告]
发表于 2016-07-21 11:28 |只看该作者
本帖最后由 jason680 于 2016-07-21 11:29 编辑

回复 3# hztj2005

$ perl num_chk.pl
PASSED: 五十九万三千一百
PASSED: 二百零四万
PASSED: 一千零五十万零四十
PASSED: 七千万五千
PASSED: 二亿二千万
PASSED: 十三亿一千万
FAILED: 四十九点五八十
PASSED: 四十九点五八
PASSED: 六又七分之一
PASSED: 百分之九十四点五
FAILED: 四十五三万三千一百七十百五点六八
FAILED: 四十五万三千一百七十百五点六八

$ cat num_chk.pl
use strict;
use warnings;
use utf8;
binmode(STDIN, ':encoding(utf8)');
binmode(STDOUT, ':encoding(utf8)');

my $sNum = "一二三四五六七八九";
my $sHun = "百";
my $sTho = "千";
my $sTen = "十";

sub num_chk{
  my($_) = @_;
  if(m/点/){
    if(! m/点[$sNum]+$/){
      return 1;
    }
    s/点.+$//;
  }
  return 2 if(m/[$sNum]{2}/);

  s/^百分之//;
  s/[$sNum]+//g;
  return 3 if(m/${sTen}[$sTen$sHun$sTho]/);
  return 4 if(m/${sHun}[$sHun$sTho]/);
  return 5 if(m/${sTho}[$sTho]/);

  # more check by yourself

  return 0;
}
while(<DATA>){
  chomp;
  if(num_chk($_)){
    print "FAILED: $_\n";
  }
  else{
    print "PASSED: $_\n";
  }

}

__DATA__
五十九万三千一百
二百零四万
一千零五十万零四十
七千万五千
二亿二千万
十三亿一千万
四十九点五八十
四十九点五八
六又七分之一
百分之九十四点五
四十五三万三千一百七十百五点六八
四十五万三千一百七十百五点六八

   

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
6 [报告]
发表于 2016-07-21 13:46 |只看该作者
这么一看, 验证汉子数字的逻辑 相当复杂啊, 我的那个太小儿科了. 哈哈哈!

论坛徽章:
0
7 [报告]
发表于 2016-07-22 00:34 |只看该作者
回复 5# jason680

谢谢大侠出手!
有一点没看懂,就是下面几行中的${sTen}、${sHun}、${sTho}是什么意义?什么语法?
我看关于花括号都是{n},表示重复的次数,

return 3 if(m/${sTen}[$sTen$sHun$sTho]/);
   return 4 if(m/${sHun}[$sHun$sTho]/);
   return 5 if(m/${sTho}[$sTho]/);

再次谢谢!


   

论坛徽章:
6
15-16赛季CBA联赛之新疆
日期:2016-03-22 22:34:5915-16赛季CBA联赛之山东
日期:2016-04-11 09:08:41程序设计版块每日发帖之星
日期:2016-06-28 06:20:00程序设计版块每日发帖之星
日期:2016-07-19 06:20:00每日论坛发贴之星
日期:2016-07-19 06:20:0015-16赛季CBA联赛之青岛
日期:2016-07-20 22:44:17
8 [报告]
发表于 2016-07-22 00:45 |只看该作者
这题真的很大--
Json大神code:
PASSED: 三亿万
PASSED: 三万万
PASSED: 三万十

论坛徽章:
6
15-16赛季CBA联赛之新疆
日期:2016-03-22 22:34:5915-16赛季CBA联赛之山东
日期:2016-04-11 09:08:41程序设计版块每日发帖之星
日期:2016-06-28 06:20:00程序设计版块每日发帖之星
日期:2016-07-19 06:20:00每日论坛发贴之星
日期:2016-07-19 06:20:0015-16赛季CBA联赛之青岛
日期:2016-07-20 22:44:17
9 [报告]
发表于 2016-07-22 01:45 |只看该作者

u

本帖最后由 RE_HASH 于 2016-07-22 05:37 编辑

尽力了,不保证没有漏的:
use utf8;
binmode(STDIN, ':encoding(utf8)');
binmode(STDOUT, ':encoding(utf8)');
sub CheckNumber
{
  my $N = $_[0];
  return "Failed (Decimal)" if (exists $N->{'.'} && $N->{'.'} =~ /\D/);
  delete $N->{'.'};
  return "Failed (Missing 零)" if (exists $N->{万} && exists $N->{个} && $N->{个} !~ /^(\d千|0)/);
  return "Failed (Missing 零)" if (exists $N->{亿} && exists $N->{万} && $N->{万} !~ /^(\d千|0)/);
  return "Failed (Missing 零)" if (exists $N->{亿} && ! exists $N->{万} && exists $N->{个} && $N->{个} !~ /^(\d千|0)/);
  foreach (keys %$N)
  {
          return "Failed (Unit $_)" unless ($N->{$_} =~ /^(\d千)?(\d百|0)?(\d十|0)?\d?$|^十\d$/);
  }
  
  
  return "Passed";
}

while(<DATA>){
  chomp;
  print;
  my $P;
  tr/一二三四五六七八九零点/1234567890./;
  s/^百分之//;
  s:(\d+)分之(\d+):($2/$1):e;
  s/又0\././;
  #printf "=$_";
  s/(\.(.+))/$P->{'.'} = $2; ''/eg;
  s/$/个/;
  s/(.+?)([万亿个])/$P->{$2} = $1; ''/eg;
  printf "\t%s\n", CheckNumber$P;
  
}

__DATA__
五十九万三千一百
二百零四万
一千零五十万零四十
七千万五千
二亿二千万
十三亿一千万
四十九点五八十
四十九点五八
六又七分之一
百分之九十四点五
四十五三万三千一百七十百五点六八
四十五万三千一百七十百五点六八
三亿万
三万万
三万十
三万二十

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
10 [报告]
发表于 2016-07-22 02:54 |只看该作者
这个匹配表达式用普通的正则难以描述,因为涉及的变化太多,用 grammar 设计也许还行。Perl6 比较轻松的搞定。
  1. 五千六百七十万亿六千八百万一千零四
复制代码
从前往后,单位由大到小,但每个单位前,又可能从大到小。

亿万都可能会重复。
  1. 四万万投资,刺激基础建设投资。
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP