Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5359671
  • 博文数量: 1144
  • 博客积分: 11974
  • 博客等级: 上将
  • 技术积分: 12312
  • 用 户 组: 普通用户
  • 注册时间: 2005-04-13 20:06
文章存档

2017年(2)

2016年(14)

2015年(10)

2014年(28)

2013年(23)

2012年(29)

2011年(53)

2010年(86)

2009年(83)

2008年(43)

2007年(153)

2006年(575)

2005年(45)

分类: LINUX

2009-11-29 16:45:03

perl 对文件排序经典实例(2009-10-20 16:26:40)标签:perl sort map 文件 排序 杂谈   分类:perl语言学习
perl 排序问题【实例】1
月份       电话号码             市话      长途      总话费(元)
-----------------------------------------------------------------------
200809        74889999        3.0        6.6        188
200810        74885444        4.0        1.0        200
200810        74885555        0.8        5.5        120
200810        74889888        4.0        1.0        200
要求:1,按月份(从小到大)排序。
          2,按总花费(从大到小)排序。若总话费相等,则按号码(从小到大)排序
          首先,按月份排序。同时,按总花费(从大到小)排序,若总话费相等,则按号码(从小到大)排序
最佳答案:
print map {$_->[-1]}
    sort {$a->[0] <=> $b->[0] || $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2]}
    map {[(split)[0,4,1],$_]} ;
__DATA__
200809        74889999        3.0        6.6        188
200810        74885444        4.0        1.0        200
200810        74885555        0.8        5.5        120
200810        74889888        4.0        1.0        200
也可以这样:
#!/usr/bin/perl
use warnings;
use strict;
open (INFILE,"/home/liuguiyou/11.txt");
my @a=;
my @b;
@b= map {$_->[3]}
    sort {$a->[0] <=> $b->[0] ||$b->[1] <=> $a->[1] ||$b->[2] <=> $a->[2]}
    map {[(split)[0,4,1],$_]} @a;
close INFILE;
foreach (@b){
         print "$_"; 
             }
注:
第一:@b= map {$_->[3]}  是因为需要打印输出的位置前面已经有了3个元素,在这里可以写为@b= map {$_->[-1]},指的是从最后一个位置开始计算。
第二:sort {$a->[0] <=> $b->[0] ||$b->[1] <=> $a->[1] ||$b->[2] <=> $a->[2]}
            是因为下面有三个条件,按照顺序[0,4,1], 并且这些条件之间用||分开
任何可以从 $a 和 $b 中得到的有用信息都可以在一个排序过程中比较的基础来用。比如,如果多行文本要根据特定域来排序,那么可以在排序过程中使用 split 以获取该域:

   @sorted_lines = sort {
      @a_fields = split /:/, $a;      # 冒号分隔的域
      @b_fields = split /:/, $b;
        
      $a_fields[3] <=> $b_fields[3]   # 对第四个域进行数字排序,然后
         ||
      $a_fields[0] cmp $b_fields[0]   # 对第一个域进行字串排序,然后
         ||
      $b_fields[2] <=> $a_fields[2]   # 对第三个域进行数字反向排序
      ...            # 等等
   } @lines;
 
 

perl 排序问题【实例】2
#!/usr/bin/perl
@by_uid = map { $_->;[0]} sort {$a->;[1] <=>; $b->;[1] } map { [$_,(split /:/)[2]] } ;;
for(@by_uid){print ."\n";}
__DATA__
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/dev/null
rpm:x:37:37::/var/lib/rpm:/bin/bash
ident:x:98:98:pident user:/:/sbin/nologin
pcap:x:77:77::/var/arpwatch:/sbin/nologin
sshd:x:501:501::/dev/null:/dev/null
mysql:x:100:101:MySQL server:/var/lib/mysql:/bin/bash
cnhackTNT:x:0:0::/home/cnhackTNT:/bin/bash
chutium:x:504:504:Seraph Chutium:/home/chutium/:/bin/bash
源代码:
@by_uid = map { $_->;[0]} sort {$a->;[1] <=>; $b->;[1] } map { [$_,(split /:/)[2]] } ;;
以下对上面的根据uid来排序的code做出解释:
第一:;实际上可以看成一个数组,内容就是__DATA__下的那些,这里我们把它当作是@DATA这个数组(Apile原文里就是/etc下的passwd文件的内容)。
第二:map{[$_,(split /:/)[2]}从@DATA中取出每条数据,并对每条数据以 : 作为分割符分割,也就是 split(/:/,$_);然后返回一个数组@_,以sshd:x:501:501::/dev/null:/dev/null为例,那么这个返回的数组中的一项可以看成:$_=['sshd:x:501:501::/dev/null:/dev/null','501'];
从上可看出这个$_是一个匿名的数组引用,他实际上包含两个部分,其中第二部分是uid,也就是$_->;[1]
现在@_中的内容变成了:
....前面的省略.....
['rpm:x:37:37::/var/lib/rpm:/bin/bash','37']
['ident:x:98:98:pident user:/:/sbin/nologin,'98']
['pcap:x:77:77::/var/arpwatch:/sbin/nologin','77']
['sshd:x:501:501::/dev/null:/dev/null','501']
....后面的省略.....

第三:sort {$a->;[1] <=>; $b->;[1] }便是根据@_中的每项(实际上是数组引用)的第二部分uid的大小来排序,这里的sort排序是标准的方法,很多书里都有例子。
现在,经过上面的过程,数组@_中的内容已经以uid大小排好序了,现在我们只要按@_排好的顺序读取每一项内容的第一部分,以['sshd:x:501:501::/dev/null:/dev/null','501']为例,我们要取他的第一部分 'sshd:x:501:501::/dev/null:/dev/null',也就是$_->;[0],并将其保存到数组@by_uid中就好了,而map { $_->;[0]}很好的完成了这项工作。
实际上只要明掌握了map,sort的用法就能容易的理解上面算法的意思
转自
类似的问题:



阅读(3091) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~