美文网首页
perl语言实现合并首列相同的行,需要用到多少知识点?

perl语言实现合并首列相同的行,需要用到多少知识点?

作者: 食品猪的生信鸡 | 来源:发表于2021-05-22 12:15 被阅读0次

有这样一种数据类型:

假设它有很多很多行(1.txt)

我想将它整理成这样:

它也有很多很多行(2.txt)

直接给出一段代码:

#! C:\other_disk\D_disk_software\perl64 -w
use utf8;
binmode(STDOUT,":utf8");
my %hash;
sub uniq { 
    return keys %{{map {$_=>1} @_}}; 
    }
open(INPUT,"<1.txt")or die, $!;
open(OUTPUT,">2.txt")or die, $!;
foreach (<INPUT>) {
  if(/^(\S+)(\s.*?)[\n\r]*$/){ 
    $hash{$1} .= $2;
  }
}
close INPUT;
foreach (sort keys %hash) {
  my @elements = uniq (split ('\t', $hash{$_})); 
  print OUTPUT "$_\t", join(' ', sort @elements), "\n";
}
这段代码包含了perl语言的很多知识点。

我们来一行一行的看(接下来将用数字表示代码的行数,一行一行的进行解释):

------------------------------------------------------------------

1. #! C:\other_disk\D_disk_software\perl64 -w

我写的这段代码,对于windows系统下毫无意义,只是觉得应该在第一行写点什么东西。但是假如你在linux系统中运用perl的话,需要分两种情况来说明:第一种,如果你采用perl text.pl这种方式运行perl的脚本文件text.pl的话,那第一行也不需要,直接开始写你的代码就可以。第二种,如果你采用./text.pl来执行这个脚本文件,那么第一行必不可少,一般大家都这么写: #!/usr/bin/perl (指明perl解释器的路径)。

------------------------------------------------------------------

2. use utf8;

这是载入utf8模块函数use,一般书写perl脚本是需要把所有你需要用到的模块在脚本的开头载入。(模块包括包,包包括函数,函数又叫子程序,也就是说一个模块可能包含许多个包和许多个函数)。

------------------------------------------------------------------

3. binmode(STDOUT,":utf8");

ok,说曹操曹操就到,binmode就是utf8模块中的一个函数这行代码的意思是perl的标准输出采用utf8编码表(编码和计算机的原理有很大关系,这说起来话长,简单点说就是,假如你和别人对暗号的时候,这个暗号必须是在同一个密码本上的暗号,假如你用的密码本和别人不同,你就会被乱枪射死,在计算机上就会出现perl语言输出的文本为乱码)。
注意:其对应的标准输入的文件格式也要utf8。

------------------------------------------------------------------

4. my %hash;

就是声明一个私有哈希列表类似与C语言的声明变量,就是告诉计算机给我准备一个叫%hash的列表,我准备向里面存取东西了。说到哈希,这里不得不提@arrey(数组),$var(变量)。perl语言中都有专门的符号表示他们。

------------------------------------------------------------------

5. 6. 7.
sub uniq { 
              return keys %{{map {$_=>1} @_}};
 }

这其实也是一个函数啦,又叫子程序,sub uniq{}指建立一个名字叫unqi的函数,其核心内容是位于{}中的代码块return keys %{{map {$_=>1} @_}};

这里说到函数就需要说函数参数的问题,使用函数就是向函数内部传递参数的过程函数就是为了实现改变几个参数就可以重复利用的功能。perl语言中@_就是接受传入函数参数的默认数组 $_也是perl语言的一个默认变量

map {$_=>1} @_中map为一个函数,它实现的功能是遍历数组@_中的每一个元素,并执行{$_=>1}中的内容,即生成一个数组(第一个元素,1,第二个元素,1,第三个元素,1,...)。

接下在的知识点就是数组、哈希以及列表的嵌套功能。当将%{{数组}}形式出现时就将数组转化为哈希,即(第一个元素=>1,第二个元素=>1,第三个元素=>1,...)。最后一步return keys %{}就是将哈希中的键列出并返回给函数。所以呀,这个函数会返回一个字符串

------------------------------------------------------------------

8. 9.
open(INPUT,"<1.txt")or die, $!;
open(OUTPUT,">2.txt")or die, $!;

两行代码实际上本质一样,第一行是将1.txt文件中的内容写入到句柄INPUT中,第二行是将句柄OUTPUT的内容写入到中2.txt文件中。

后面的or die, $!是指,如果前面的操作无法运行,则退出不在运行该脚本,并返回错误原因($!)。$!是perl中默认代表所有错误的一个标志吧。

------------------------------------------------------------------

10. 11. 12. 13. 14. 15.
foreach (<INPUT>) {
  if(/^(\S+)(\s.*?)[\n\r]*$/){ #以任意个非空白字符开头,以任意个换行符或者回车符结尾的字符串(并且中间可以包含新行外的一个或者多个任意字符)
    $hash{$1} .= $2;
  }
}
close INPUT;

foreach (<INPUT>)就是遍历文件句柄IUPUT中的内容,一行一行的来,有多少行就循环多少次每一行执行一次代码块中的内容。

if(/^(\S+)(\s.*?)[\n\r]*$/)假如...成立执行代码块中的内容。

下面我们只需要深究这个/^(\S+)(\s.*?)[\n\r]*$/是什么意思。//表示匹配,即/匹配内容/^以...字符开头,$表示以...字符结尾,因此意思就是以空字符开头以0个或者任意个换行符或者以0个或者任意个回车符结尾字符串,并且中间包含(\S+)任意个非空白字符(\s.*?)任意字符串

$hash{$1} .= $2

也可以写成

$hash{$1} = $hash{$1}.$2

$1就默认表示(\S+)中的内容,$2表示(\s.*?)中的内容。.代表将两个字符串合并

因此,整个foreach循环结束后,就生成一个哈希(%hash)表包括:('1'=>'\ta\tk','2'=>'\tb\tl','3'=>'\tc\tm',...)

最后,养成好习惯,关闭句柄INPUT,节约内存。

------------------------------------------------------------------

16. 17. 18. 19
foreach (sort keys %hash) {
  my @elements = uniq (split ('\t', $hash{$_})); 
  print OUTPUT "$_\t", join(' ', sort @elements), "\n";
}

sort keys %hash%hash的键列出,并排序,相当于键值组成了一个列表。接着还是用foreach遍历这个列表,一个元素一个循环

split ('\t', $hash{$_})$hash中键对应的值分割成数组,比如第一行(a,k),再将这个数组作为参数传递到uniq函数中,因此,my @element就是(a,k)

join(' ', sort @elements)数组元素空格连接成一个字符串,即a k

最后print OUTPUT "$_\t", join(' ', sort @elements), "\n";,以键+字符串+换行符为格式打印到OUTPUT句柄中,每个键执行一个循环,知道所有键都执行完毕为止。

最终,OUTPUT句柄写入到2.txt文件中。

-------------------------------------------------------------------

源代码来源:

http://cn.voidcc.com/question/p-otfupjcv-rz.html(略作修改)

参考文章**

https://www.cnblogs.com/dancheblog/p/3528000.html

相关文章

网友评论

      本文标题:perl语言实现合并首列相同的行,需要用到多少知识点?

      本文链接:https://www.haomeiwen.com/subject/qienjltx.html