免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3989 | 回复: 55

[文本处理] 快过节了,来点技术小红包,awk/sed程序方面 [复制链接]

论坛徽章:
0
发表于 2017-01-14 22:04 |显示全部楼层
本帖最后由 mcwolf2000 于 2017-01-20 10:22 编辑

这个题目准备当做实习生小项目,用awk程序解决应该是合适的(当然其他方案也可以考虑),多年没有玩Shell了,不知道难度是否合适。

共准备500块微信红包意思一下,活跃一下气氛,鼓励一下在论坛里面无私解答的各位兄弟。
第一个完善解决的200-300红包,后面的就看情况分了。//参与的情况好,春节期间还搞几个技术红包玩玩!
发邮件,584418273@qq.com,默认公布脚本,不愿意公布说明一下啊!

...............红包活动基本就这样了,也欢迎继续改进...........
目前提出的方案都测试OK,小数据量性能测试应该差别不明显,大数据量(13楼sunzhiguolu的测试方法)实际上很大部分要看优化,不太容易比较。
1.haooooaaa的awk方法    jason680也是awk方法针对后面提出的具体场景有了优化

2.moperyblue的sed方法


3.sunzhiguolu的Perl实现的程序化文本处理方法

4.本友会机友会摄友会(27楼)的powershell ConvertFrom-String: Example-based text parsing模板定义式匹配方式
   本友会机友会摄友会对于大数据量又用powershell实现了一个分片的程序化处理方法

有同事提出能用lex/yacc搞定是对实践使用一种很有吸引力的方案,但这是不是需要放在编译器论坛去了
=====================================

问题:如下文本文件内容
  Id     : 1
  Params :
    Enable     : enabled       MediaType      : 1000BaseT
    Duplex         : auto          Speed          : auto
    DefaultVlanId  : 1             FlowControl    : disabled
    Multicastfilter: default       Security       : disabled
    SpeedAdvertise : maxSpeed      Mdix           : auto
    AcceptFrame    : all           Jumbo          : disabled
    MTU            : 1522B         ProtocolVlan   : disabled
    EgressTPID     : 0x8100        PortVlanJump   : disabled
  Status :
    Class      : 802.3         Link           : down
    Duplex         : half          Speed          : 10Mbps
    DownTime       : 0 years   0 days  0 hours  5 minutes 51 seconds
    RecentUpTime   : 0 years   0 days  0 hours  0 minutes  0 seconds

Id     :2
  Params :
    Enable     : enabled       MediaType      : 1000BaseT
    Duplex         : auto          Speed          : auto
    DefaultVlanId  : 1             FlowControl    : disabled
    Multicastfilter: default       Security       : disabled
    SpeedAdvertise : maxSpeed      Mdix           : auto
    AcceptFrame    : all           Jumbo          : disabled
    MTU            : 1522B         ProtocolVlan   : disabled
    EgressTPID     : 0x8100        PortVlanJump   : disabled
  Status :
    Class      : 802.3         Link           : down
    Duplex         : half          Speed          : 10Mbps
    DownTime       : 0 years   0 days  0 hours  5 minutes 51 seconds
    RecentUpTime   : 0 years   0 days  0 hours  0 minutes  0 seconds

......

要求:
通过Shell脚本(awk/sed)转换成格式(类csv,逗号分割):
port   Enable            MediaType      Duplex     ...... PortClass        Link           Duplex      RecentUpTime        
1       enable            1000BaseT      auto        ......  802.3           down           half          0 years   0 days...
2       enabled      
....
说明:
1.这里每个ID代表一行开始,字段有params和Status两大类(需考虑某行没有出现某个字段的情况,用null代替),字段的分割有点间接(每个字段及其值是用:来分割,字段间是换行来分割,但个别字段DownTime的值中也有空格(这种字段"一般"占据一行),一般来说处理的时候是大小写不敏感

2.同事提出实际使用中最好能进行字段控制,这样题目比较完整。
  比如用一个文本文件或者常量数组的字段列表 fieldlist=("port","Enable","MediaType","Duplex","speed","Class","link",“RecentUpTime”):
   一是文本文件中没有出现fieldlist中的字段,该字段取null;   二是文本文件中超出fieldlist范围的字段,忽略本字段。
(本来关于字段控制,同事提示要补充说明完善一下,想着太晚就没有写,结果haooooaaa昨天都搞定了)
例如: fieldlist=("port","nofield",”Enable","MediaType","Duplex","speed","Class","link",“RecentUpTime”),这里加了个nofield字段。输出csv如下(有两个字段都叫Duplex/speed,实际上是不同字段,输出csv后再处理也不麻烦,就先名字重复吧)
port   nofield   Enable           MediaType      Duplex   speed   class       Link           Duplex     speed             RecentUpTime        
1       null       enable           1000BaseT      auto      auto     802.3     down          half         10Mbps            0 years   0 days...
2       null       enable           100BaseT        auto      auto     802.3     down          half         100Mbps          0 years   0 days...



既然有字段控制,那有时候自然有行控制的需求,比如获取第N行记录的脚本(2017.1.20)......

3. 本问题背景context
关于解决方法的评估和性能测试,实际上各种解决方案没有一个绝对的评价。因为本来就是不同角度解决问题的方法。因为在不同的应用环境下只有最合适的方案!

本问题的背景是:企业网络环境中存在数十个不同厂家不同系列的数百台网络设备,就想到一个JOB_ShowPort:
【a】. 我想收集这些“异构”网络设备(这里暂时定为接入层交换机)的某一项配置信息(这里是端口信息),就如上述文本文件内容表示;
【b】. 将这些信息通过脚本进行处理,生成规范化的格式(单步或者管道等连接的多步),输出一个csv文件,如上述脚本运行的结果 ;
【c】. 将这些规范化后的csv导入数据库(load data infile "/home/result_101.csv" into table switch_101("port",",”Enable","MediaType","Duplex","speed_param","speed_status","link",“RecentUpTime”); )
【e】. 当然这些必然在一个自动任务中去完成,定时收集或者用户发起收集信息(这么多异构,而且有大量文本处理工作,选择telnet/ssh远程获取配置,而不用snmp);
【e】. 上层应用是类似Nagios这样的东东,展现这些收集的数据。同时也要管理这些任务、脚本、设备的参数。

这个红包问题是上面【b】步骤要解决的问题,在本context下:
对于某一类型的(这里暂时定为接入层交换机)网络设备的主要配置信息,各厂家各型号的【语义】是差不多,但【语法】上具有复杂性,随意性,不可预测性(我自己开发网络设备时被迫写过这样的垃圾配置,也处理过很多厂家变态的配置文件)。
因此需要一个处理的框架,在实际项目中希望减轻面对不同网络设备时,描述某类配置信息格式的工作量,而且要进行人员分派和培训:
(1). 正则类:对于大多数设备类型,可能是期望用awk/sed这样的正则类进行描述,当然还需要分派的开发人员对正则有一定的了解,然后模仿上面的就差不多了;
(2). 模板类:powershell模板识别还不太熟悉,其灵活度和适应性以及和其它处理工具配合性有待观察。但这个方法对本案的吸引力在于即使是一般的技术人员都可以稍加培训就可以完成描述任务,我个人非常喜欢这种方式(如果能达到我需要的健壮性要求的话),可惜暂时没有Linux版本;
(3). 程序类:sunzhiguolu这段perl代码所用的程序化处理方式适合那些实在是变态的或者很难正则化的配置文件,在实际系统中也是必须要保底支持的,当然麻烦一点需要程序员出马了。















论坛徽章:
54
2015亚冠之德黑兰石油
日期:2015-07-07 13:00:1615-16赛季CBA联赛之深圳
日期:2016-03-31 09:03:5415-16赛季CBA联赛之辽宁
日期:2016-05-09 20:38:15程序设计版块每日发帖之星
日期:2016-05-12 06:20:0015-16赛季CBA联赛之四川
日期:2016-05-13 15:19:4715-16赛季CBA联赛之福建
日期:2016-05-15 20:24:34每日论坛发贴之星
日期:2016-05-16 06:20:0015-16赛季CBA联赛之吉林
日期:2016-05-26 11:49:4715-16赛季CBA联赛之广东
日期:2016-05-26 13:49:18极客徽章
日期:2016-12-07 14:05:2315-16赛季CBA联赛之广夏
日期:2016-12-20 17:33:532017金鸡报晓
日期:2017-01-10 15:19:56
发表于 2017-01-14 23:50 |显示全部楼层
本帖最后由 haooooaaa 于 2017-01-15 09:09 编辑
  1. cyg@win /tmp$ awk -F: '{gsub(" *: *",":");sub("^ *","");$0=gensub("(:[^ ]+) *([^ ]+:)","\\1:\\2","g",$0);$1=$1}/^Id/{a[$2];b=$2;next}NF>1&&length($2){for(i=1;i<=NF/2;i++){key[$(i*2-1)];all[b,$(i*2-1)]=$(i*2)}}END{s="port";for(i in key)s=s","i;l=split(s,t,",");print s;for(i in a){s=i;for(j=2;j<=l;j++)s=s ","(all[i,t[j]]?all[i,t[j]]:"NULL");print s}}' file
  2. port,PortVlanJump,Link,SpeedAdvertise,RecentUpTime,EgressTPID,ProtocolVlan,Security,DefaultVlanId,MTU,DownTime,FlowControl,MediaType,Jumbo,Speed,AcceptFrame,Multicastfilter,Duplex,Enable,Class,Mdix
  3. 1,disabled,down,maxSpeed,0 years   0 days  0 hours  0 minutes  0 seconds,0x8100,disabled,disabled,1,1522B,0 years   0 days  0 hours  5 minutes 51 seconds,disabled,1000BaseT,disabled,10Mbps,all,default,half,enabled,802.3,auto
  4. 2,disabled,down,maxSpeed,0 years   0 days  0 hours  0 minutes  0 seconds,0x8100,disabled,disabled,1,1522B,0 years   0 days  0 hours  5 minutes 51 seconds,disabled,1000BaseT,disabled,10Mbps,all,default,half,enabled,802.3,auto
复制代码
  1. awk -F: '{gsub(" *: *",":");sub("^ *","");$0=gensub("(:[^ ]+) *([^ ]+:)","\\1:\\2","g",$0);$1=$1}/^Id/{a[$2];b=$2;next}!/^Params|^Status|^ *$/{for(i=1;i<=NF/2;i++){key[$(i*2-1)];all[b,$(i*2-1)]=$(i*2)?$(i*2):"NULL"}}END{s="port";for(i in key)s=s","i;l=split(s,t,",");print s;for(i in a){s=i;for(j=2;j<=l;j++)s=s ","all[i,t[j]];print s}}' file
复制代码



论坛徽章:
0
发表于 2017-01-14 23:57 |显示全部楼层
回复 2# haooooaaa

这么快就搞定了,搞得我怀疑题目太简单了......

感谢回复,看起来不错,先意思一下,CU打赏太麻烦了。周一才有时间测试,测试后再接着打赏。





论坛徽章:
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
发表于 2017-01-15 00:23 |显示全部楼层
Id     : 1
  Params :
    Enable     : enabled       MediaType      : 1000BaseT
    Duplex         : auto          Speed          : auto
    DefaultVlanId  : 1             FlowControl    : disabled
    Multicastfilter: default       Security       : disabled
    SpeedAdvertise : maxSpeed      Mdix           : auto
    AcceptFrame    : all           Jumbo          : disabled
    MTU            : 1522B         ProtocolVlan   : disabled
    EgressTPID     : 0x8100        PortVlanJump   : disabled
  Status :
    Class      : 802.3         Link           : down
    Duplex         : half          Speed          : 10Mbps
    DownTime       : 0 years   0 days  0 hours  5 minutes 51 seconds
    RecentUpTime   : 0 years   0 days  0 hours  0 minutes  0 seconds

以第一条记录为例,完整的输出结果啥样?

论坛徽章:
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
发表于 2017-01-15 00:46 |显示全部楼层
需考虑某行没有出现某个字段的情况,用null代替

如何界定 某个字段确定为没有值,举例中似乎没有缺值情形的举例。并没有给出处理的条件,
Id     :2
  Params :
    Enable     : enabled       MediaType      : 1000BaseT
    Duplex         :              Speed          : auto

论坛徽章:
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
发表于 2017-01-15 09:14 |显示全部楼层
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. local $/ = '';
  5. my ($id, %hData) = ('', ());
  6. while (<>){
  7.     $id = $1 if (s/(.*)\n//);
  8.     $id = $1 if ($id =~ /(\d+)/);
  9.     for (split /\n/){
  10.         s/\s*:\s*/:/g;
  11.         next if (/:\z/);
  12.         if (/\b(DownTime|RecentUpTime):(.*)/){
  13.             $hData{$id}{$1} = $2;
  14.             next;
  15.         }
  16.         for (split (' ', $_)){
  17.             my %hT = split (/:/, $_);
  18.             $hData{$id}{$_} = $hT{$_} for keys %hT;
  19.         }
  20.     }
  21. }

  22. my @aKeys = sort {$a cmp $b} keys %{$hData{$id}};
  23. print join (',', @aKeys), "\n";
  24. foreach my $id (sort {$a cmp $b} keys %hData){
  25.     my @aT = ();
  26.     push (@aT, $id);
  27.     push (@aT, $hData{$id}{$_} // 'NULL') for @aKeys;
  28.     print join (',', @aT), "\n";
  29. }
复制代码

perl abc.pl urFile
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AcceptFrame,Class,DefaultVlanId,DownTime,Duplex,EgressTPID,Enable,FlowControl,Jumbo,Link,MTU,Mdix,MediaType,Multicastfilter,PortVlanJump,ProtocolVlan,RecentUpTime,Security,Speed,SpeedAdvertise
1,all,802.3,1,0 years   0 days  0 hours  5 minutes 51 seconds,half,0x8100,enabled,disabled,disabled,down,1522B,auto,1000BaseT,default,disabled,disabled,0 years   0 days  0 hours  0 minutes  0 seconds,disabled,10Mbps,maxSpeed
2,all,802.3,1,0 years   0 days  0 hours  5 minutes 51 seconds,half,0x8100,enabled,disabled,disabled,down,1522B,auto,1000BaseT,default,disabled,disabled,0 years   0 days  0 hours  0 minutes  0 seconds,disabled,10Mbps,maxSpeed

论坛徽章:
211
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:322015亚冠之全北现代
日期:2016-05-11 17:05:27操作系统版块每日发帖之星
日期:2016-05-10 19:23:04操作系统版块每日发帖之星
日期:2016-05-10 19:23:04操作系统版块每日发帖之星
日期:2016-05-10 19:23:04操作系统版块每日发帖之星
日期:2016-05-10 19:23:04操作系统版块每日发帖之星
日期:2016-05-10 19:22:58数据库技术版块每日发帖之星
日期:2016-05-10 19:23:04数据库技术版块每日发帖之星
日期:2016-05-10 19:23:04操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
发表于 2017-01-15 09:33 |显示全部楼层
支持一下活动,真金白银的就是诚意

论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
发表于 2017-01-15 09:42 |显示全部楼层

1. 结果中指标的顺序有限制吗? 从上到下从左到右?
2. Speed , DownTime这两个指标需要显示吗?

论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
发表于 2017-01-15 10:08 |显示全部楼层

more file
  1. Id     : 1
  2.   Params :
  3.     Enable     : enabled       MediaType      :
  4.     Duplex         : auto          Speed          : auto
  5.     DefaultVlanId  : 1             FlowControl    : disabled
  6.     Multicastfilter: default       Security       : disabled
  7.     SpeedAdvertise : maxSpeed      Mdix           : auto
  8.     AcceptFrame    : all           Jumbo          : disabled
  9.     MTU            : 1522B         ProtocolVlan   : disabled
  10.     EgressTPID     : 0x8100        PortVlanJump   : disabled
  11.   Status :
  12.     Class      : 802.3         Link           : down
  13.     Duplex         : half          Speed          : 10Mbps
  14.     DownTime       : 0 years   0 days  0 hours  5 minutes 51 seconds
  15.     RecentUpTime   : 0 years   0 days  0 hours  0 minutes  0 seconds


  16. Id     :2
  17.   Params :
  18.     Enable     : enabled       MediaType      :
  19.     Duplex         : auto          Speed          : auto
  20.     DefaultVlanId  : 1             FlowControl    : disabled
  21.     Multicastfilter: default       Security       : disabled
  22.     SpeedAdvertise : maxSpeed      Mdix           : auto
  23.     AcceptFrame    : all           Jumbo          : disabled
  24.     MTU            : 1522B         ProtocolVlan   : disabled
  25.     EgressTPID     : 0x8100        PortVlanJump   : disabled
  26.   Status :
  27.     Class      : 802.3         Link           : down
  28.     Duplex         : half          Speed          : 10Mbps
  29.     DownTime       : 0 years   0 days  0 hours  5 minutes 51 seconds
  30.     RecentUpTime   : 0 years   0 days  0 hours  0 minutes  0 seconds
复制代码

  1. grep -oP '(DownTime|RecentUpTime)\s*:.*|(\S+\s*:\s*\S*)' file|sed -r '/Params|Status/d;s/\bId/port/;s/Enable|Class/port&/;s/:/ & /'|awk -F'\\s*:\\s*' '!f{a=a?a","$1:$1;b=b?b","($2?$2:"NULL"):($2?$2:"NULL");if(/RecentUpTime/)f=1}f&&!p{print a RS b;p=1;next}p{printf ($2?$2:"NULL") (/RecentUpTime/?RS:",")}'
复制代码
  1. port,portEnable,MediaType,Duplex,Speed,DefaultVlanId,FlowControl,Multicastfilter,Security,SpeedAdvertise,Mdix,AcceptFrame,Jumbo,MTU,ProtocolVlan,EgressTPID,PortVlanJump,portClass,Link,Duplex,Speed,DownTime,RecentUpTime
  2. 1,enabled,NULL,auto,auto,1,disabled,default,disabled,maxSpeed,auto,all,disabled,1522B,disabled,0x8100,disabled,802.3,down,half,10Mbps,0 years   0 days  0 hours  5 minutes 51 seconds,0 years   0 days  0 hours  0 minutes  0 seconds
  3. 2,enabled,NULL,auto,auto,1,disabled,default,disabled,maxSpeed,auto,all,disabled,1522B,disabled,0x8100,disabled,802.3,down,half,10Mbps,0 years   0 days  0 hours  5 minutes 51 seconds,0 years   0 days  0 hours  0 minutes  0 seconds
复制代码

论坛徽章:
0
发表于 2017-01-15 11:17 |显示全部楼层
本帖最后由 mcwolf2000 于 2017-01-15 11:36 编辑

回复 2# haooooaaa

感谢大家的参与.......
haooooaaa 第一个完成的暂时按10*20计算啊,CU的打赏太累,方便的话邮件告诉我微信号。是否完善的标准主要看有没有新的更优秀方案,后者你自己方案的改进吧。红包发完为止......

--几年没有发东西,CU居然封了我的博客。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

基于案例的 SQL 优化实战训练营

讲师:中电福富特级专家梁敬彬,参与本次课程培训,你将收获:
1. 能编写出较为高效的 SQL;
2. 能解决70%以上的数据库常见优化问题;
3. 能得到老师提供的高效的相关工具和解决方案;
4. 能举一反三,收获不仅仅是 SQL 优化。
现在购票享受8.8折优惠!
----------------------------------------
优惠时间:2019年3月20日前

大会官网>>
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP