忘记密码   免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12下一页
最近访问板块 发新帖
查看: 1426 | 回复: 13

[文本处理] 数据类型的自动识别 [复制链接]

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-29 06:17 |显示全部楼层
大家好,我有一个问题向大家请教。

我有一个很大的文本,以下是从其中一个样本中提取的部分内容。
grahamx
6713568
CHOWDHARY Ashish
10077158
LIAO Wei-Rehn
JF0139662
+86041132326000
kewong
michael.shieh@aol.com
61401543
BC0013246
WANG Xiao Qiang
+447513170113
jchan013
ZHU Zhu Zhengqiao
4613714
13717260688

文本中每行是一条数据。
但是数据的类型是杂乱无章的,需要根据数据的特征进行识别。

字母大小写视为相同;
统一识别码(upi):长度9位,由前两位字母和后七位数字构成,例如:FQ7003397
员工ID(uid):长度3-8位,全部字母或者字母加3位数字构成,例如:bgates;fbi007
员工姓名(name):长度不定,全部由字母构成,姓和名之间有一个或多个空格,例如:Bill Gates;Liu De Hua
员工邮箱(email):长度不定,格式为firstname.lastname@company.com,例如:bill.gates@microsoft.com
员工编号(employeenumber):长度7位,全部由数字构成,例如:9064765
座位编号(seatid):长度8位,全部由数字构成,例如:69053830
员工手机(mobile):长度11位以上,全部由数字构成,最前面可能有+号也可能没有,例如:13012345678;+8618611112222;+358503006000

希望对这些数据进行处理后自动识别出数据类型并将数据类型和数据本身一起输出,姓名的空格用%20替换。
uid=grahamx
employeenumber=6713568
name=CHOWDHARY%20Ashish
seatid=10077158
name=LIAO%20Wei-Rehn
upi=JF0139662
mobile=+86041132326000
uid=kewong
email=michael.shieh@aol.com
seatid=61401543
upi=BC0013246
name=WANG%20Xiao%20Qiang
mobile=+447513170113
uid=jchan013
name=ZHU%20Zhu%20Zhengqiao
employeenumber=4613714
mobile=13717260688

谢谢大家!


论坛徽章:
19
程序设计版块每日发帖之星
日期:2016-05-03 06:20:0015-16赛季CBA联赛之山西
日期:2018-08-07 19:46:2315-16赛季CBA联赛之佛山
日期:2018-08-03 13:19:33黑曼巴
日期:2018-07-06 15:19:5015-16赛季CBA联赛之八一
日期:2018-07-05 10:34:0915-16赛季CBA联赛之八一
日期:2018-07-03 16:56:4615-16赛季CBA联赛之深圳
日期:2018-06-15 14:59:3715-16赛季CBA联赛之青岛
日期:2018-06-08 13:45:2815-16赛季CBA联赛之同曦
日期:2018-06-04 19:42:2015-16赛季CBA联赛之山东
日期:2018-05-30 12:44:59CU十四周年纪念徽章
日期:2018-05-15 11:36:3815-16赛季CBA联赛之广东
日期:2018-05-14 09:52:42
发表于 2018-03-29 12:02 |显示全部楼层
回复 1# bikkuri


  1. awk 'BEGIN{IGNORECASE=1;a[1]="^[a-z]{2}[0-9]{7}$";b[1]="upi=";a[2]="^[a-z]{3,8}$|^[a-z]{1,5}[0-9]{3}$";b[2]="uid=";a[3]="^[a-z-]+( +[a-z-]+){1,}$";b[3]="name=";a[4]="^[a-z]+[.][a-z]+@[a-z]+[.][a-z]+$";b[4]="email=";a[5]="^[0-9]{7}$";b[5]="employeenumber=";a[6]="^[0-9]{8}$";b[6]="seatid=";a[7]="^+?[0-9]{11,}$";b[7]="mobile="}{for(i=1;i<=7;i++){gsub(a[i],b[i]$0);$0=$0~b[3]?gensub(" +","%20","g"):$0}}1' file
复制代码

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-29 12:10 |显示全部楼层
回复 2# wh7211

非常感谢您的帮助!

论坛徽章:
130
技术图书徽章
日期: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
发表于 2018-03-29 20:35 |显示全部楼层
回复 1# bikkuri

$ awk -f get_type.awk file
uid=grahamx
employeenumber=6713568
name=CHOWDHARY%20Ashish
seatid=10077158
***Error***: unknow type
LIAO Wei-Rehn

upi=JF0139662
mobile=+86041132326000
uid=kewong
email=michael.shieh@aol.com
seatid=61401543
upi=BC0013246
name=WANG%20Xiao%20Qiang
mobile=+447513170113
uid=jchan013
name=ZHU%20Zhu%20Zhengqiao
employeenumber=4613714
mobile=13717260688

$ cat get_type.awk

# WYTIWYC (What You Think Is What You Code)

func re(pat, type){
  ++c;
  p[c] = pat
  t[c] = type
}

func out(str){
  gsub(" ","%20");
  print str"="$0
}

BEGIN{

  # 统一识别码(upi):长度9位,由前2位字母和后7位数字构成
  # 例如:FQ7003397
  re("^[a-zA-Z]{2}[0-9]{7}$", "upi");

  # 员工ID(uid):长度3-8位,全部字母或者字母加3位数字构成
  # 例如:bgates;fbi007
  re("^([a-zA-Z]{3,8}|[a-zA-Z]{0,5}[0-9]{3})$", "uid");

  # 员工编号(employeenumber):长度7位,全部由数字构成
  # 例如:9064765
  re("^[0-9]{7}$", "employeenumber");

  # 座位编号(seatid):长度8位,全部由数字构成,例如:69053830
  re("^[+]?[0-9]{8}$", "seatid");

  # 员工手机(mobile):长度11位以上,全部由数字构成,最前面可能有+号也可能没有
  # 例如:13012345678;+8618611112222;+358503006000
  re("^[+]?[0-9]{11,}$", "mobile");

  # 员工邮箱(email):长度不定,格式为firstname.lastname@company.com
  # 例如:bill.gates@microsoft.com
  re("^[a-zA-Z]+[.][a-zA-Z]+@[a-zA-Z.]+$", "email");

  #员工姓名(name):长度不定,全部由字母构成,姓和名之间有一个或多个空格
  #例如:Bill Gates;Liu De Hua
  re("^[a-zA-Z ]+$", "name");

}

{
  for(n=1; n<=c; n+=1){
    if($0 ~ p[n]){
      out(t[n]);
      next;
    }
  }
  print "***Error***: unknow type\n"$0;
}

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-29 23:06 |显示全部楼层
回复 4# jason680

谢谢您的帮助!
  #员工姓名(name):长度不定,全部由字母构成,姓和名之间有一个或多个空格
  #例如:Bill Gates;Liu De Hua

这一条我没有说清楚,员工姓名除了字母还可以有减号-。
谢谢您指出了我的这一处疏漏。

在处理大量数据中,可能还会不断地碰到不符合规则的特例,我会根据情况修改脚本。

谢谢大家的帮助。

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-30 04:22 |显示全部楼层
[ 本帖最后由 bikkuri 于 2018-03-30 04:51 编辑 ]\n\n我在awk 4.0.2上测试了两位的脚本都可以得到正确的结果,但是在awk 3.1.7上却不能得到正确的结果。
┌─[Fri Mar 30 04:18:27 CST 2018]
└─[root@hp8:/tmp]# awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see [url]http://www.gnu.org/licenses/.[/url]
┌─[Fri Mar 30 04:19:24 CST 2018]
└─[root@hp8:/tmp]# awk -f a.awk a
name=grahamx
***Error***: unknow type
6713568
name=CHOWDHARY%20Ashish
***Error***: unknow type
10077158
***Error***: unknow type
LIAO Wei-Rehn
***Error***: unknow type
JF0139662
***Error***: unknow type
+86041132326000
name=kewong
email=michael.shieh@aol.com
***Error***: unknow type
61401543
***Error***: unknow type
BC0013246
name=WANG%20Xiao%20Qiang
***Error***: unknow type
+447513170113
***Error***: unknow type
jchan013
name=ZHU%20Zhu%20Zhengqiao
***Error***: unknow type
4613714
***Error***: unknow type
13717260688
┌─[Fri Mar 30 04:19:33 CST 2018]
└─[root@hp8:/tmp]# cat a|awk 'BEGIN{IGNORECASE=1;a[1]="^[a-z]{2}[0-9]{7}$";b[1]="upi=";a[2]="^[a-z]{3,8}$|^[a-z]{1,5}[0-9]{3}$";b[2]="uid=";a[3]="^[a-z-]+( +[a-z-]+){1,}$";b[3]="name=";a[4]="^[a-z]+[.][a-z]+@[a-z]+[.][a-z]+$";b[4]="email=";a[5]="^[0-9]{7}$";b[5]="employeenumber=";a[6]="^[0-9]{8}$";b[6]="seatid=";a[7]="^+?[0-9]{11,}$";b[7]="mobile="}{for(i=1;i<=7;i++){gsub(a[i],b[i]$0);$0=$0~b[3]?gensub(" +","%20","g"):$0}}1'
grahamx
6713568
CHOWDHARY Ashish
10077158
LIAO Wei-Rehn
JF0139662
+86041132326000
kewong
email=michael.shieh@aol.com
61401543
BC0013246
WANG Xiao Qiang
+447513170113
jchan013
ZHU Zhu Zhengqiao
4613714
13717260688
┌─[Fri Mar 30 04:20:04 CST 2018]
└─[root@hp8:/tmp]#

可以修改一下兼容两种awk版本吗?

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-30 05:40 |显示全部楼层
我发现awk 3.1.7下好像gsub不能识别{2}这样的限定符...

┌─[Fri Mar 30 05:34:33 CST 2018]
└─[root@hp8:/tmp]# echo "JF0139662"|awk '{gsub(/^[a-zA-Z]{2}[0-9]+$/,"upi="$0)}1'
JF0139662
┌─[Fri Mar 30 05:34:41 CST 2018]
└─[root@hp8:/tmp]# echo "JF0139662"|awk '{gsub(/^[a-zA-Z][a-zA-Z][0-9]+$/,"upi="$0)}1'
upi=JF0139662
┌─[Fri Mar 30 05:34:53 CST 2018]
└─[root@hp8:/tmp]#


郁闷啊...怎么会这样!
有一半的服务器是RHEL7.3以上的,awk版本是4.0.2;还有一半服务器是RHEL6.3到RHEL6.8,awk版本是3.1.7。

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-30 06:22 |显示全部楼层

awk 3.1.7下awk加--posix参数后可以识别限定符{2}了。
┌─[Fri Mar 30 05:53:36 CST 2018]
└─[root@hp8:/tmp]# echo "JF0139662"|awk --posix '{gsub(/^[a-zA-Z]{2}[0-9]+$/,"upi="$0)}1'
upi=JF0139662
┌─[Fri Mar 30 05:54:00 CST 2018]
└─[root@hp8:/tmp]#

将wh7211君的代码做如下修改以后,在awk3.1.7和awk4.0.2上可以得到相同的正确结果。
┌─[Fri Mar 30 06:18:13 CST 2018]
└─[root@hp8:/tmp]# cat a|awk --posix 'BEGIN{a[1]="^[a-zA-Z]{2}[0-9]{7}$";b[1]="upi=";a[2]="^[a-zA-Z]{3,8}$|^[a-zA-Z]{1,5}[0-9]{3}$";b[2]="uid=";a[3]="^[a-zA-Z-]+( +[a-zA-Z-]+){1,}$";b[3]="name=";a[4]="^[a-zA-Z]+[.][a-zA-Z]+@[a-zA-Z]+[.][a-zA-Z]+$";b[4]="email=";a[5]="^[0-9]{7}$";b[5]="employeenumber=";a[6]="^[0-9]{8}$";b[6]="seatid=";a[7]="^[+0-9]{11,}$";b[7]="mobile="}{for(i=1;i<=7;i++){gsub(a[i],b[i]$0)}gsub(/\ +/,"%20")}1'
uid=grahamx
employeenumber=6713568
name=CHOWDHARY%20Ashish
seatid=10077158
name=LIAO%20Wei-Rehn
upi=JF0139662
mobile=+86041132326000
uid=kewong
email=michael.shieh@aol.com
seatid=61401543
upi=BC0013246
name=WANG%20Xiao%20Qiang
mobile=+447513170113
uid=jchan013
name=ZHU%20Zhu%20Zhengqiao
employeenumber=4613714
mobile=13717260688
┌─[Fri Mar 30 06:18:38 CST 2018]
└─[root@hp8:/tmp]#

------------------------------------------------------------------------------------------
┌─[Fri Mar 30 06:15:14 CST 2018]
└─[root@shinagawa:/tmp]# cat a|awk --posix 'BEGIN{a[1]="^[a-zA-Z]{2}[0-9]{7}$";b[1]="upi=";a[2]="^[a-zA-Z]{3,8}$|^[a-zA-Z]{1,5}[0-9]{3}$";b[2]="uid=";a[3]="^[a-zA-Z-]+( +[a-zA-Z-]+){1,}$";b[3]="name=";a[4]="^[a-zA-Z]+[.][a-zA-Z]+@[a-zA-Z]+[.][a-zA-Z]+$";b[4]="email=";a[5]="^[0-9]{7}$";b[5]="employeenumber=";a[6]="^[0-9]{8}$";b[6]="seatid=";a[7]="^[+0-9]{11,}$";b[7]="mobile="}{for(i=1;i<=7;i++){gsub(a[i],b[i]$0)}gsub(/\ +/,"%20")}1'
uid=grahamx
employeenumber=6713568
name=CHOWDHARY%20Ashish
seatid=10077158
name=LIAO%20Wei-Rehn
upi=JF0139662
mobile=+86041132326000
uid=kewong
email=michael.shieh@aol.com
seatid=61401543
upi=BC0013246
name=WANG%20Xiao%20Qiang
mobile=+447513170113
uid=jchan013
name=ZHU%20Zhu%20Zhengqiao
employeenumber=4613714
mobile=13717260688
┌─[Fri Mar 30 06:21:29 CST 2018]
└─[root@shinagawa:/tmp]#


谢谢!

论坛徽章:
6
程序设计版块每日发帖之星
日期:2016-05-11 06:20:00操作系统版块每日发帖之星
日期:2016-05-12 06:20:00每日论坛发贴之星
日期:2016-05-12 06:20:00操作系统版块每日发帖之星
日期:2016-05-14 06:20:00程序设计版块每日发帖之星
日期:2016-05-31 06:20:00每日论坛发贴之星
日期:2016-05-31 06:20:00
发表于 2018-03-30 16:57 |显示全部楼层
回复 2# wh7211

$0=$0~b[3]
就是等于号后面的赋值于前面的
~不大懂,可否解释一下
~/x/ 这一种是匹配 x 的意思
linux sed # /x/  # 匹配x

论坛徽章:
17
辰龙
日期:2014-05-21 21:01:4115-16赛季CBA联赛之北控
日期:2016-11-28 18:26:3815-16赛季CBA联赛之佛山
日期:2016-11-03 11:18:5815-16赛季CBA联赛之辽宁
日期:2016-07-10 16:09:4115-16赛季CBA联赛之江苏
日期:2016-02-20 23:09:20程序设计版块每日发帖之星
日期:2015-12-31 06:20:022015亚冠之塔什干棉农
日期:2015-08-17 19:49:49程序设计版块每日发帖之星
日期:2015-06-04 22:20:00程序设计版块每日发帖之星
日期:2015-06-04 16:12:382015年亚洲杯之日本
日期:2015-04-30 01:24:342015年亚洲杯之约旦
日期:2015-04-01 00:37:182015年迎新春徽章
日期:2015-03-04 09:57:09
发表于 2018-03-31 20:41 |显示全部楼层
回复 9# 1cpuer

$0=$0~b[3]?gensub(" +","%20","g"):$0
等价于:
if($0~b[3])$0=gensub(" +","%20","g")


您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:wangnan@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP