用Perl处理语言信息问题之一

Posted 小试机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Perl处理语言信息问题之一相关的知识,希望对你有一定的参考价值。

上一篇中整理了Perl的基本语法知识,详见:https://mp.weixin.qq.com/s/p4lOc98OKeYSJRTFfbN6nw 本篇列举几个Perl在语言信息处理方面的使用,例子代码全部来自于《实战Perl——语言信息处理利器》一书,代码稍作了些改动(挺好的一本书,有需要的可以买来看看),本篇是Perl的简单应用。废话不多说,直接上例子。

统计文件词频

任务:词表文件ci_biao.txt文件中存储了很多词语,并且一行仅有一个词语,内容如下图所示,要求从此文件中读取词语数据,统计每个词语出现的次数和频率。

期望结果:

用Perl处理语言信息问题之一

代码实现:

 
   
   
 
  1. #实现思想:读取文件每一行,然后建立一个key是词语,value是次数的散列(或者叫哈希)。同时记录总的词语数,最后遍历输出key和value,得到每个词语出现的频率和频次。

  2. #!/usr/bin/perl -w

  3. use strict;

  4. use warnings;

  5. my %hash;

  6. #打开进行词表文件

  7. open(In, "ci_biao.txt") or die "Can't not open this file: $!";

  8. #统计词表中总的词数,以便计算词出现的频率

  9. my $i = 0;

  10. while (my $line = <In>) {

  11.        #去掉换行符

  12.        chomp($line);

  13.        #查找当前的词是否在散列中,如果在,频次加1,否则频次设置为1

  14.        if (defined $hash{$line}) {

  15.                $hash{$line}++;

  16.        }else{

  17.                $hash{$line}=1;

  18.        }

  19.        $i++;

  20. }

  21. close(In);

  22. #遍历输出结果

  23. foreach my $element (sort keys %hash) {

  24.        my $tf = $hash{$element}/$i;

  25.        print "$element $tf $hash{$element} ";

  26. }

合并两个词表

任务:有两个词表,将两个词表合并, 保证合并后的词表中没有重复的词语 两个词表如下所示: 

用Perl处理语言信息问题之一

用Perl处理语言信息问题之一

 期望结果:

用Perl处理语言信息问题之一

代码实现:

 
   
   
 
  1. #实现思想:利用哈希key唯一的特性,以词语作为key,key相同的情况下会相互覆盖,最后输出所有的key,就是去重后的词表

  2. #!/usr/bin/perl -w

  3. use strict;

  4. use warnings;

  5. #打开一个词表文件

  6. my %hash;

  7. open(In1, "ci_biao1.txt") or die "Can't not open this file: $!";

  8. while (<In1>) {

  9.        chomp;

  10.        $hash{$_} = 1;

  11. }

  12. close(In1);

  13. #打开另一个词表,并进行去重的操作

  14. open(In2, "ci_biao2.txt") or die "Can't not open this file: $!";

  15. while (<In2>) {

  16.        chomp;

  17.        $hash{$_} = 1;

  18. }

  19. close(In2);

  20. #输出去重后的词表

  21. foreach my $element (sort keys %hash) {

  22.        print $element." ";

  23. }

求两个词表的交集

任务:打印出两个词表中相同的词语,词表仍然使用 cibiao1.txt 和 cibiao2.txt. 期望结果:

用Perl处理语言信息问题之一

代码实现:

 
   
   
 
  1. #实现思路:先将一个词表的信息读入哈希变量中,然后读取另一个词表的词语,在哈希变量中查找,如果找到则认为是共同的词语,并打印出来

  2. #!/usr/bin/perl -w

  3. use strict;

  4. use warnings;

  5. #打开一个词表文件

  6. my %hash;

  7. open(In1, "ci_biao1.txt") or die "Can't not open this file: $!";

  8. while (<In1>) {

  9.    chomp;

  10.    $hash{$_} = 1;

  11. }

  12. close(In1);

  13. #打开另一个词表,并进行去重的操作

  14. open(In2, "ci_biao2.txt") or die "Can't not open this file: $!";

  15. while (<In2>) {

  16.    chomp;

  17.    if (defined $hash{$_}) {

  18.        print "$_ ";

  19.    }

  20. }

  21. close(In2);

查词表

任务:给定一个带有译文的词表文件,具体内容见图4,编写Perl程序,实现用户输入一个单词,程序输出该单词的译文,如果找不到,则输出 no found.

词表文件:

代码实现:

 
   
   
 
  1. #实现思想:以词表文件中的单词为key,单词的译文为value,存入哈希中。查询就是以输入的单词为key,查到结果并打印出来。

  2. #!/usr/bin/perl -w

  3. use strict;

  4. use warnings;

  5. #读取词典文件

  6. my %hash;

  7. open(In1, "dict.txt") or die "Can't not open this file: $!";

  8. while (<In1>) {

  9.    chomp;

  10.    #以 => 进行切割成单词和译文

  11.    my @array = split("=>");

  12.    #去除单词前后的空格

  13.    $array[0] =~ s/(^s+|s+$)//g;

  14.    $array[1] =~ s/(^s+|s+$)//g;

  15.    $hash{$array[0]} = $array[1];

  16. }

  17. close(In1);

  18. #while循环接收用户多次输入,直到用户输入 q 时退出

  19. while (1) {

  20.    print "please input a word ('q' for exit): ";

  21.    my $input = <>;

  22.    chomp($input);

  23.    if ($input eq 'q') {

  24.        print "exit! ";

  25.        exit(0);

  26.    }

  27.    #查找单词

  28.    if (defined $hash{$input}) {

  29.        print "translation: $hash{$input} ";

  30.    }else{

  31.        print "no found! ";

  32.    }

  33. }

汉语分词

任务:分词是将一句话划分成一个个独立的单词。例如:爱是恒久忍耐,又有恩慈。分词之后为:爱/是/恒久/忍耐,又/有/恩慈。(书中的原话,这句话出自圣经·新约)本例采用最大正向分词法进行分词。 例如:读入 '爱是持久忍耐',检索词表,并没有发现 '爱是持久忍耐'一词,则删除末尾一个字,变成'爱是持久忍',继续检索词表,直到找到一个完整的词,然后检索除这个词以外的部分,递归执行。

输入:爱是恒久忍耐,又有恩慈。 期望输出:爱/是/恒久/忍耐,又/有/恩慈。

代码实现:

 
   
   
 
  1. #实现思想:把词表读入哈希变量中,并记录词表词语的最大长度。

  2. #读入用户输入后,通过不断的删除最右边的一个字后,检索词表,找到命中的词语,加上 / ,然后递归检索剩下的部分。

  3. #!/usr/bin/perl -w

  4. use strict;

  5. use warnings;

  6. #读取词表文件的内容

  7. my $maxLen = 0;

  8. my %mapDict;

  9. ReadDict("word.txt");

  10. print "please input a sentence:('q' for exit): =>";

  11. while (1) {

  12.    my $sentence = <>;

  13.    chomp($sentence);

  14.    if ($sentence eq 'q') {

  15.        exit;

  16.    }

  17.    #调用额分词函数进行分词

  18.    my $result = Segment($sentence);

  19.    print $result;

  20. }

  21. #读取词表信息,同时记录最大的长度

  22. sub ReadDict {

  23.    my ($Dict) = @_;

  24.    open(In, $Dict) or die "Can't not open this file:$!";

  25.    #记录词表中最长的词语的长度

  26.    while (my $line = <In>) {

  27.        chomp($line);

  28.        $mapDict{$line} = length($line);

  29.        if (length($line) > $maxLen) {

  30.            $maxLen = length($line);

  31.        }

  32.    }

  33.    close(In);

  34. }

  35. #分词

  36. sub Segment {

  37.    my ($aSentence) = @_;

  38.    #$segm为分词后结果,$remain为还需要分词的部分

  39.    my $segm = "";

  40.    my $remain = $aSentence;

  41.    while (length($remain) > 0) {

  42.        my $flag = 0; #代表是否从词表中找到该词

  43.        #如果没有匹配,则将当前的字符强制判断为一个词语

  44.        for (my $i = $maxLen; $i > 1; $i--) {

  45.            my $matchStr = substr($remain, 0, $i);

  46.            if (defined $mapDict{$matchStr}) {

  47.                $segm .= $matchStr."/";

  48.                $remain = substr($remain, $i, length($remain) - $i);

  49.                $flag = 1;

  50.                last;

  51.            }

  52.        }

  53.        if ($flag == 0) {

  54.            $segm .= substr($remain, 0, 1)."/";

  55.            $remain = substr($remain, 1, length($remain) - 1);

  56.        }

  57.    }

  58.    return $segm;

  59. }

参考文献

[1]荀恩东,黄志娥,饶高琦,谢佳丽.实战Perl——语言信息处理利器[M].北京:清华大学出版社,2013.

关于小试机


以上是关于用Perl处理语言信息问题之一的主要内容,如果未能解决你的问题,请参考以下文章

这是不是perl语言的快速入门通道呢?

perl编程:正则匹配

小白的perl语言之数据分割

Perl,R,Python在生物信息学中是怎样的角色?

LaTeX 排版的《生物信息学 Perl 语言入门》

perl的更新与模块的安装