免费注册 查看新帖 |

Chinaunix

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

<请教>perl批量处理3000个文件 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2017-03-04 10:40 |只看该作者 |倒序浏览
本帖最后由 gtluck 于 2017-03-04 10:41 编辑

每个文件不超过80行数据,都是有规律性的.
比如:
time:20170101
dog data
     name = aaaaaa...
     birthday = 20000101 15:00:00...
     gender=male...
     healthy = nok...
dog data
     name = bbbb...
     birthday = 20151201 14:23:23...
     gender=male...
      healthy = nok...
........
......
......
每个文件第一行都是文件的保存时间。

现在的需求是读取指定name的dog data,如果文件中包含此name,而且time-birthday>10,healthy不为nok的,就获取该文件的文件名,最终生成一个文件名的列表,请问大家有好的方法吗?

我想了一天没想到perl处理的的好方法,真诚请教论坛大神的指点。

论坛徽章:
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 [报告]
发表于 2017-03-04 12:05 |只看该作者
根据你提出的问题,我进行了一下整理,如有不正确的地方 请给予指正 谢谢。
1.>
如你所说,每个文件都是固定格式数据项。即
dog data
     name = bbbb...
     birthday = 20151201 14:23:23...
     gender=male...
      healthy = nok...
如上所示,可以看作一个完整的数据项。
其中有一个问题不是很理解,dog data 对于每个数据项来说是否为固定值?

2.>
筛选条件,查找数据项中具有指定值的 name 键。
并且
time-birthday > 10,这个值是如何得来的。请给出具体示例。
并且
healthy 不为 nok 的,该项的取值都有哪些?请给出示例。

最后,输出结果中。不论每个文件包含多少个数据项 只要有一个数据项满足以上条件 那么就显示该文件名? 还是有其他要求?

论坛徽章:
0
3 [报告]
发表于 2017-03-04 12:28 |只看该作者
本帖最后由 gtluck 于 2017-03-04 12:31 编辑

回复 2# sunzhiguolu

非常感谢你的回复。我详细描述下我的问题:

1. 如你所说,每个文件都是固定格式数据项。即
dog data
      name = bbbb...
      birthday = 20151201 14:23:23...
      gender=male...
       healthy = nok...
如上所示,可以看作一个完整的数据项。
其中有一个问题不是很理解,dog data 对于每个数据项来说是否为固定值?

-------------------------------------------------------------------------------
dog data 对于每个数据项是固定值,每个完整数据项都包含dog data字段。我举文件a为例子,如下为其打印:
time:20170101
dog data
      name = bbbb...
      birthday = 20151201 14:23:23...
      gender=male...
       healthy = nok...



dog data
      name = bbbb...
      birthday = 20151201 14:23:23...
      gender=male...
       healthy = nok...



dog data
      name = cccc...
      birthday = 20151202 15:23:23...
      gender=male...
       healthy = nok...

每个文件的第一行为文件的保存时间即time:20170101, 每个完整数据项之间有一个空行。


2.>
筛选条件,查找数据项中具有指定值的 name 键。
并且
time-birthday > 10,这个值是如何得来的。请给出具体示例。
并且
healthy 不为 nok 的,该项的取值都有哪些?请给出示例。

最后,输出结果中。不论每个文件包含多少个数据项 只要有一个数据项满足以上条件 那么就显示该文件名? 还是有其他要求?
-----------------------------------
查找name=bbbb的:
time-birthday>10即求两个的时间差,小于10个小时, time即为文件的保存时间即time:20170101,birthday为这个完整数据项中的birthday:20151201 14:23:23;
healthy不为nok,该项取值还有很多,可能还有healthy=nok   abc,这样的。
上面只是一个举例,实际情况需要查询的name有10多个。
  不论每个文件包含多少个数据项 只要有一个数据项满足以上条件 那么就显示该文件名?  是的,只要有一个数据项满足条件就输出其文件名。

论坛徽章:
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 [报告]
发表于 2017-03-04 14:31 |只看该作者
time  -  birthday  >  10   即求两个的时间差,小于10个小时
你的要求是用文件的保存时间 即开头的 time 字段的年月日 如本例中的 20170101 与 数据项中的每个 birthday 键的完整日期时间进行减法操作 (20151201 14:23:23),
在其他条件满足的情况下,如果时间差 (小于 还是 大于) 10 小时的则满足输出条件 这样?

论坛徽章:
0
5 [报告]
发表于 2017-03-04 15:06 |只看该作者
回复 4# sunzhiguolu

是的,需要大于10个小时,矫正一下文本第一行的时间格式,以秒的形式显示的:
dog data 对于每个数据项是固定值,每个完整数据项都包含dog data字段。我举文件a为例子,如下为其打印:
now:1488448457
dog data
       name = bbbb...
       birthday = 20151201 14:23:23...
       gender=male...
        healthy = nok...



dog data
       name = bbbb...
       birthday = 20151201 14:23:23...
       gender=male...
        healthy = nok...



dog data
       name = cccc...
       birthday = 20151202 15:23:23...
       gender=male...
        healthy = nok...

每个文件的第一行为文件的保存时间即time:20170101, 每个完整数据项之间有一个空行

论坛徽章:
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 [报告]
发表于 2017-03-04 16:37 |只看该作者
本帖最后由 sunzhiguolu 于 2017-03-04 17:05 编辑

回复 5# gtluck
cat a.txt
------------------------
now:1488448457
dog data
       name = bbbb
       birthday = 20151201 14:23:23
       gender=male
        healthy = nok


dog data
       name = bbbb
       birthday = 20151201 14:23:23
       gender=male
        healthy = nok


dog data
       name = cccc
       birthday = 20151202 15:23:23
       gender=male
        healthy = nok

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Time::Local;
  5. use Time::Seconds;

  6. foreach my $path (glob ('urPath:\\*.txt')){
  7.     open (my $FHr, '<', $path);
  8.     my $now = $1 if (<$FHr> =~ /(\d+)/);
  9.     local $/ = '';
  10.     while (<$FHr>){
  11.         my @aItems = (split ("\n", $_))[1, 2, -1];
  12.         next if ($aItems[0] =~ /(\S+)\z/ and $1 ne 'bbbb');
  13.         next if ($aItems[-1] =~ /(\S+)\z/ and $1 eq 'nok');
  14.         my @aTimes = $aItems[1] =~ /(\d{4})(\d{2})(\d{2})\s+(\d+):(\d+):(\d+)/;
  15.         $aTimes[1] -= 1;
  16.         my $time = timegm (reverse (@aTimes));
  17.         next if (Time::Seconds->new ($now - $time)->hours <= 10);
  18.         print $path, "\n";
  19.         last;
  20.     }
  21.     close ($FHr);
  22. }
复制代码



论坛徽章:
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
7 [报告]
发表于 2017-03-04 16:37 |只看该作者
本帖最后由 sunzhiguolu 于 2017-03-04 16:44 编辑

回复 5# gtluck
cat a.txt
------------------------
now:1488448457
dog data
       name = bbbb
       birthday = 20151201 14:23:23
       gender=male
        healthy = nok


dog data
       name = bbbb
       birthday = 20151201 14:23:23
       gender=male
        healthy = ok


dog data
       name = cccc
       birthday = 20151202 15:23:23
       gender=male
        healthy = nok

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Time::Local;
  5. use Time::Seconds;

  6. foreach my $path (glob ('urPath:\\*.txt')){
  7.     open (my $FHr, '<', $path);
  8.     my $now = $1 if (<$FHr> =~ /(\d+)/);
  9.     local $/ = '';
  10.     while (<$FHr>){
  11.         my @aItems = (split ("\n", $_))[1, 2, -1];
  12.         next if ($aItems[0] =~ /(\S+)\z/ and $1 ne 'bbbb');
  13.         next if ($aItems[-1] =~ /(\S+)\z/ and $1 eq 'nok');
  14.         my @aTimes = $aItems[1] =~ /(\d{4})(\d{2})(\d{2})\s+(\d+):(\d+):(\d+)/;
  15.         $aTimes[1] -= 1;
  16.         my $time = timegm (reverse (@aTimes));
  17.         next if (Time::Seconds->new ($now - $time)->hours <= 10);
  18.         print $path, "\n";
  19.         last;
  20.     }
  21.     close ($FHr);
  22. }
复制代码



论坛徽章:
0
8 [报告]
发表于 2017-03-04 17:17 |只看该作者
本帖最后由 gtluck 于 2017-03-04 17:19 编辑

回复 7# sunzhiguolu
多谢大师指点~
我对Perl还不是很熟悉,我看了下,大致意思是先用空行替换换行符,然后按块读入数据,每一块就是一个完整数据项,然后对每个块的数据项进行处理。学习了先进思路。
顺便还想请教下我是在bash语句中定义的各种文件路径变量,然后通过bash调用perl脚本,请问如何将变量传到perl脚本里面啊,非常感谢。因为我是定义的定时Job,每次生成的文件路径不一样。

  • #!/usr/bin/perl
  • use strict;
  • use warnings;
  • use Time::Local;
  • use Time::Seconds;
  • foreach my $path (glob ('urPath:\\*.txt')){
  •     open (my $FHr, '<', $path);
  •     my $now = $1 if (<$FHr> =~ /(\d+)/);
  •     local $/ = '';
  •     while (<$FHr>{
  •         my @aItems = (split ("\n", $_))[1, 2, -1];
  •         next if ($aItems[0] =~ /(\S+)\z/ and $1 ne 'bbbb');
  •         next if ($aItems[-1] =~ /(\S+)\z/ and $1 eq 'nok');
  •         my @aTimes = $aItems[1] =~ /(\d{4})(\d{2})(\d{2})\s+(\d+)\d+)\d+)/;
  •         $aTimes[1] -= 1;
  •         my $time = timegm (reverse (@aTimes));
  •         next if (Time::Seconds->new ($now - $time)->hours <= 10);
  •         print $path, "\n";
  •         last;
  •     }
  •     close ($FHr);
  • }


论坛徽章:
0
9 [报告]
发表于 2017-03-04 17:18 |只看该作者
回复 7# sunzhiguolu

感觉论坛回帖有点问题。

论坛徽章:
0
10 [报告]
发表于 2017-03-04 17:49 |只看该作者
回复 6# sunzhiguolu

关于您贴的代码有两点请教一下:
1.第一行是如何跳过去,再分块的,没看明白,我的理解是没有跳过第一行,只是取了第一行的时间,但是带着这一行分快那不第一个数据块格式不对吗?

2. 这一行$aItems[0]匹配非空字符结尾,已经取到了name = bbbb这一行了,为什么$1读取到的是bbb,而不是name啊?
next if ($aItems[0] =~ /(\S+)\z/ and $1 ne 'bbbb');

非常感谢。

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP