免费注册 查看新帖 |

Chinaunix

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

[已解决]批量查找字符串并导出结果到新的文本 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-01 19:30 |只看该作者 |倒序浏览
本帖最后由 smile1129 于 2016-07-19 19:45 编辑

新学perl,请大家指点!

要求是:
某文件夹下有众多大文本文件,我要查找含特定字符串1、字符串2等的行,将上述行导出到新建文本,1个字符串的搜索结果建1个文本(文件名就是该字符串),有多少个字符串就建多少个文本,字符串包含在2.txt文档中,一行1个。

比如:E:\TEXT 下有a.txt  b.txt  c.txt 等,  
我要查找的字符串在2.txt中,字符串如下:
beijing
shanghai
wuhan
等;
我希望在E:\TEXT 目录下文本中分别查找含有上述字符串的行,输出结果为beijing.txt    shanghai.txt  wuhan.txt



以下是查找1个字符串导出到文本的方法,仅供参考! 请大家帮忙修改使之达到上面的要求,谢谢大家!
  1. #!/usr/bin/perl -w
  2. open OUT1,'+>E:/3.txt';
  3. printf"write the path you want to search files:";
  4. $searchdir=<STDIN>;
  5. chomp $searchdir;
  6. printf "Input search string:";
  7. $searchstr=<STDIN>;
  8. chomp $searchstr;
  9. opendir(DIRHANDLE,$searchdir) || die "Cann't open $searchdir !";
  10. while($file=readdir DIRHANDLE) {
  11.         if (-d "$searchdir/$file") {
  12.                 printf "$searchdir/$file is a directory! ";
  13.         } else {
  14.                 open(FileHandle, "$searchdir/$file") || die "cann't open $searchdir/$file ! ";
  15.                 $lines=1;
  16.                 while (defined($line=<FileHandle>)) {
  17.                         $back=index($line,$searchstr);
  18.                         if ( $back != -1 ) {
  19.                                 print OUT1 "$line";
  20.                         }
  21.                 $lines=$lines+1;
  22.                 }
  23.         }
  24.         close(FileHandle);
  25. }
  26. close(OUT1);
  27. closedir(DIRHANDLE);
复制代码

论坛徽章:
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-02 02:27 |只看该作者
本帖最后由 sunzhiguolu 于 2016-07-02 02:29 编辑

回复 1# smile1129
试下,
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. chdir ('urPath');
  5. open (my $fhR, '<', '2.txt');
  6. my %hData = map {chomp; $_, []} <$fhR>;
  7. close ($fhR);

  8. foreach my $fn (glob ('*.txt')){
  9.         next if ($fn eq '2.txt');
  10.         open ($fhR, '<', $fn);
  11.         while (defined (local $_ = <$fhR>)){
  12.                 foreach my $k (keys %hData){
  13.                         push(@{$hData{$k}}, $_) if (/$k/);       
  14.                 }
  15.         }
  16.         close ($fhR);
  17. }

  18. foreach (keys %hData){
  19.         open (my $fhW, '>', "$_.txt");
  20.         print $fhW @{$hData{$_}};
  21.         close ($fhW);
  22. }
复制代码

论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
3 [报告]
发表于 2016-07-02 08:46 |只看该作者
改一波,建议用use strict; 啦
  1. #!/usr/bin/perl -w
  2. # open OUT1,'+>E:/3.txt';


  3. printf"write the path you want to search files:";
  4. $searchdir=<STDIN>;
  5. chomp $searchdir;
  6. printf "Input search string, one per line, end with a single '.' :\n";
  7. $searchstr = +{};
  8. while ($line  = <STDIN>) {
  9.         $line =~ s{^\s+ | \s+$}{}gmix;
  10.         next if not $line;
  11.         last if $line eq '.';
  12.         $searchstr->{$line} = 1
  13. }

  14. # $searchstr=<STDIN>;
  15. # chomp $searchstr;
  16. opendir(DIRHANDLE,$searchdir) || die "Cann't open $searchdir !";
  17. while($file=readdir DIRHANDLE) {
  18.         if (-d "$searchdir/$file") {
  19.                 printf "$searchdir/$file is a directory! \n";
  20.         } else {
  21.                 open(FileHandle, "$searchdir/$file") || die "cann't open $searchdir/$file ! ";
  22.                 # $lines=1;
  23.                 while (defined($line=<FileHandle>)) {
  24.                         $line =~ s{^\s+ | \s+$}{}gmix;
  25.                         next if not $line;
  26.                         if (exists $searchstr->{$line}) {
  27.                                 $file = "$line.txt";
  28.                                 if (-f $file) {
  29.                                         print "Found [$line], file [$file] alreay created, no need to create again.\n";
  30.                                 }
  31.                                 else {
  32.                                         open OUT1, ">$file";
  33.                                         close(OUT1);
  34.                                         print "Found [$line], file [$file] created.\n";
  35.                                 }

  36.                         }
  37.                         # $back=index($line,$searchstr);
  38.                         # if ( $back != -1 ) {
  39.                         #         # print OUT1 "$line";
  40.                         # }
  41.                 # $lines=$lines+1;
  42.                 }
  43.                 close(FileHandle);
  44.         }
  45.         # close(FileHandle);
  46. }
  47. # close(OUT1);
  48. closedir(DIRHANDLE);
复制代码
output sample:
  1. write the path you want to search files:TEXT
  2. Input search string, one per line, end with a single '.' :
  3. beijing
  4. wuhan
  5. .
  6. TEXT/. is a directory!
  7. TEXT/.. is a directory!
  8. Found [wuhan], file [wuhan.txt] created.
  9. Found [beijing], file [beijing.txt] created.
  10. Found [wuhan], file [wuhan.txt] alreay created, no need to create again.
复制代码

论坛徽章:
0
4 [报告]
发表于 2016-07-02 09:26 |只看该作者
sunzhiguolu 发表于 2016-07-02 02:27
回复 1# smile1129
试下,

很厉害!  谢谢!


想再请教下,如何才能 不区分大小写呢? 以及把所有结果输出到1个文件3.txt中(即不分为多个文件输出了) ?

论坛徽章:
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
5 [报告]
发表于 2016-07-02 10:26 |只看该作者
本帖最后由 sunzhiguolu 于 2016-07-02 10:44 编辑

1.> 不区分大小写
push(@{$hData{$k}}, $_) if (/$k/i);


2.> 以及把所有结果输出到1个文件3.txt中(即不分为多个文件输出了)

  1. my $str;
  2. $str .= join ("", @{$hData{$_}) for keys %hData;
  3. #print $str to your FileHandle.
复制代码

论坛徽章:
0
6 [报告]
发表于 2016-07-02 16:58 |只看该作者
stanley_tam 发表于 2016-07-02 08:46
改一波,建议用use strict; 啦output sample:


谢谢,不过有个问题:

比如E:\TEXT 下有a.txt 中以下内容
beijing:010
......

查找beijing找不到,只能找到完全为beijing的行,这个有问题。

论坛徽章:
0
7 [报告]
发表于 2016-07-02 17:30 |只看该作者
sunzhiguolu 发表于 2016-07-02 10:26
1.> 不区分大小写



非常感谢您的指点,很受用!

有个疑问,我在1楼贴的查找1个字符串的代码(别的地方找的),在查找200MB文件时,我的电脑用时大概6s, 而使用你的代码大概10s。

所以想请问下,如果要追求速度的话(因为有的文本更大),您推荐怎么修改?   O(∩_∩)O谢谢

论坛徽章:
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
8 [报告]
发表于 2016-07-02 17:41 |只看该作者
回复 7# smile1129
你的需求到底是啥?

   

论坛徽章:
0
9 [报告]
发表于 2016-07-02 18:01 |只看该作者
sunzhiguolu 发表于 2016-07-02 17:41
回复 7# smile1129
你的需求到底是啥?

不好意思。
考虑到大文本处理速度很重要,想修改为:将结果导出到1个指定文件即可,另外多个字符串是否采用正则的形式会快一些,比如beijing|shanghai|wuhan,不区分大小写。

还有就是我上面说的单个字符串搜索的时候,针对大文本,我上面的代码似乎速度稍微快点点,但是我上面贴的不支持正则,你的可以写成beijing|shanghai|wuhan。


论坛徽章:
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
10 [报告]
发表于 2016-07-02 18:32 |只看该作者
本帖最后由 sunzhiguolu 于 2016-07-02 18:34 编辑

回复 9# smile1129
再试下, 在保证正确的前提下, 将代码的测试结果贴出来看下. (文件大小, 执行时间等)

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. chdir ('urPath');
  5. open (my $fhR, '<', '2.txt');
  6. my $regex = join ("|", map {s/\r?\n//r} <$fhR>);
  7. close ($fhR);

  8. my @aData;
  9. foreach my $fn (glob ('*.txt')){
  10.         next if ($fn eq '2.txt');
  11.         open ($fhR, '<', $fn);
  12.         while (defined (local $_ = <$fhR>)){
  13.             push (@aData, $_) if (/$regex/);        
  14.         }
  15.         close ($fhR);
  16. }

  17. #print @aData to your FileHandle.
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP