免费注册 查看新帖 |

Chinaunix

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

perl 如何处理这样的文本输入文件? [复制链接]

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2015-10-28 06:20:00数据库技术版块每日发帖之星
日期:2015-10-29 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-01-03 11:10 |只看该作者 |倒序浏览
本帖最后由 weichanghe2000 于 2016-01-03 11:39 编辑

大家好,请教大家一个perl处理文本文件的问题。
想了蛮久,没有想到怎么处理。
来这里求助下,先谢了哈。

读入1个txt文件,然后把该文件的每一题按照题号(1. 或者 3. 或者 4. 或 10. 或 12.)、字母序号(A. 或 B. 或 C.  或 D.  或 E. 或 F. 或 G.)存入hash中,作为hash的2个key,后面的作为value。

例如:
       $hash{1.}{A.} = 'chmop'
       $hash{1.}{D.} = 'unlink'

       $hash{10.}{B.} = 'remove'
       $hash{10.}{D.} = 'delete'

       $hash{19.}{B.} = '@nums=sort {$b <=> $a} @numbers'
       $hash{19.}{D.} = '@nums=sort {$b cmp $a} @numbers'

注意,下面的只是一个小例子,实际上,
题目序号1., 2., 1000., 或更多,
字母序号,可能更多,如有A. B. C. D. E. F. G.;
字母序号A.  B.  C.  D. 可能都在一行;也可能在4行;也可能在3行(A. B. 在1行,C. 在1行,D. 在1行)
怎样才能完全的,更健壮的?

  1. 1. which command is used to cut trailing newline?                     ( B )
  2. A. chmop           B. chomp
  3. C. chop            D. unlink

  4. 3. It is better to add a semicolon at the end of line in block        ( A )
  5. in order to build a good program style.                       
  6. A. True            B. Flase

  7. 4. which command will jump current loop and enter into another loop?  ( C )
  8. A. continue        B. break
  9. C. next            D. last      E. redo      F. done     G. do   

  10. 10.The ____ function removes the given key                            ( D )
  11. (and its corresponding value) from the hash.            
  12. A. del             B. remove        C. cut             D. delete

  13. 12.The ____ function yields a list of all the keys in a hash,         ( A )
  14. and the values function gives the corresponding values.      
  15. A. keys            B. Keys      C. values          D. value

  16. 19.How to sort an array by ascending  numeric order, such as @numbers              ( A )
  17. A. @nums=sort {$a <=> $b} @numbers      B. @nums=sort {$b <=> $a} @numbers      
  18. C. @nums=sort {$a cmp $b} @numbers      D. @nums=sort {$b cmp $a} @numbers      
复制代码

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
2 [报告]
发表于 2016-01-03 13:51 |只看该作者
回复 1# weichanghe2000


    如果给出的例子有代表性的话,下述代码应该可以:

sub load_questions {
  local @ARGV = @_;

  my (%questions, $number);

  while (<>) {                        # Begin of question
    if (/^\s* (\d+) \s* \. .* \(\s* ([A-Z]) \s*\) \s*$/x) {
      $number = $1;
      $questions{$number}{__ANSWER__} = $2;
      $questions{$number}{__QUESTION__} = $_;
    }
    elsif (not /^\s*[A-Z]\s*\./) { # Continuing of question
      $questions{$number}{__QUESTION__} .= $_;
    }
    else {                        # Answers
      my @fields = split /\s*([A-Z])\s*\.\s*/;
      shift @fields;
      my %fields = map { s/^\s*//; s/\s*$//; $_ } @fields;
      while (my ($key, $val) = each %fields) {
        $questions{$number}{$key} = $val;
      }
    }
  }

  wantarray ? %questions : \%questions;
}

还缺些错误检查,自己加上吧。

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2015-10-28 06:20:00数据库技术版块每日发帖之星
日期:2015-10-29 06:20:00
3 [报告]
发表于 2016-01-03 15:36 |只看该作者
本帖最后由 weichanghe2000 于 2016-01-03 18:01 编辑

回复 2# MMMIX

非常感谢。
但是我把你的代码贴进去,然后调用时,会报一个错。
不知道哪里出错了呢?



找到原因了,需要先去掉空行。
   

论坛徽章:
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
4 [报告]
发表于 2016-01-03 15:51 |只看该作者
本帖最后由 jason680 于 2016-01-03 15:54 编辑

回复 1# weichanghe2000

$ perl exam.pl exam.txt
1. which command is used to cut trailing newline?
     Ans ( B ) : chomp
3. It is better to add a semicolon at the end of line in block in order to build a good program style.
     Ans ( A ) : True            
4. which command will jump current loop and enter into another loop?
     Ans ( C ) : next            
10. The ____ function removes the given key (and its corresponding value) from the hash.
     Ans ( D ) : delete
12. The ____ function yields a list of all the keys in a hash, and the values function gives the corresponding values.
     Ans ( A ) : keys            
19. How to sort an array by ascending  numeric order, such as @numbers
     Ans ( A ) : @nums=sort {$a <=> $b} @numbers      


$ cat exam.pl
use strict;
use warnings;

my %hExam;
my($sNum, $sAns,$sQu);
while(<>){
    chomp;
    if(s/^(\d+)[.]//){
        $sNum = $1;
        if(! s/\( \s* (\S+) \s* \) \s*$//x){
            die "exam $sNum: can't not get Answer field\n";
        }
        $sAns = $1;
        s/^\s+|\s+$//g;
        $sQu  = $_;
        next;
    }
    if(m/^[ABCDEFG][.] /){
        my(undef, %hAns) = split(/([A-G])[.] /);
        foreach(keys %hAns){
          $hExam{$sNum}{$_} = $hAns{$_};
        }
        $hExam{$sNum}{"QU"}  = $sQu;
        $hExam{$sNum}{"ANS"} = $sAns;
        next;
    }
    next if(m/^\s*$/);
    s/^\s+|\s+$//g;
    $sQu .= " $_";
}
for(sort {$a <=> $b} keys %hExam){
  print "$_. $hExam{$_}{QU}\n";
  $sAns = $hExam{$_}{ANS};
  print "     Ans ( $sAns ) : $hExam{$_}{$sAns}\n";
}

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2015-10-28 06:20:00数据库技术版块每日发帖之星
日期:2015-10-29 06:20:00
5 [报告]
发表于 2016-01-03 16:01 |只看该作者
本帖最后由 weichanghe2000 于 2016-01-03 16:10 编辑

回复 2# MMMIX
     
      my @fields = split /\s*([A-Z])\s*\.\s*/;
      shift @fields;

这2句看了很久,没有看懂。
能够帮忙解释下吗?

我平时只用到 split /\s+/, $_, 用空格作为分隔。
我把你的加上了打印信息,但看得更加糊涂了。
1:A,   A还在,但是后面 那个. 怎么没有了呢?


   

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
6 [报告]
发表于 2016-01-03 19:58 |只看该作者
回复 5# weichanghe2000


    split 的 pattern 中若有 capture group,在返回的 list 中也会包括这些 capture group 匹配到的内容,详细看 perldoc -f split 的末尾。

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2015-10-28 06:20:00数据库技术版块每日发帖之星
日期:2015-10-29 06:20:00
7 [报告]
发表于 2016-01-03 23:25 |只看该作者
回复 6# MMMIX

非常感谢哈。
可能英语理解比较差,那几句话看了半天,理解起来还是相当费力气。
呵呵,perl基础和功底太弱了。
   

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2015-10-28 06:20:00数据库技术版块每日发帖之星
日期:2015-10-29 06:20:00
8 [报告]
发表于 2016-01-03 23:26 |只看该作者
回复 4# jason680

非常感谢大神哈。
由于自己基础很一般,需要慢慢咀嚼和消化。
慢慢体会大神的思想。

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP