Chinaunix首页 | 论坛 | 博客
  • 博客访问: 44570
  • 博文数量: 7
  • 博客积分: 173
  • 博客等级: 入伍新兵
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-06 18:31
文章分类
文章存档

2012年(7)

我的朋友

分类: Python/Ruby

2012-08-09 10:11:25

Perl自带有一系列强大的array操作函数,其中包括映射(map)、筛选(grep)、排序(sort)。它们在使用上有完全相同语法 - 都是针对array中的每个元素进行某种操作。

map { } @array
grep { } @array
sort { } @array

而具体操作是由使用者通过花括号{ }内的code或函数自己定义的。map与grep在用户自定函数中由$_来表述array中的每个元素。而sort涉及到两个元素的比较,这两个元素分别由$a和$b表述:$a是排序低的元素,$b是排序高的元素。即

map { code_that_does_something_with( $_ ) } @array
grep { code_that_selects_from( $_ ) } @array
sort { code_that_compares( $a, $b ) } @array

这些操作结合到一起使用时,可达到事半功倍的效果。泛指通过一系列的array操作函数(map, grep, sort)来简化/解决问题的手段。

我们可以通过一个小例子展示一下schwartian transform的应用:把/etc/passwd中记录的所有使用/bin/sh的用户按照uid排序打印出来。

  1. map { print $_->[0] }
  2.     sort { $a->[1] <=> $b->[1] }
  3.     grep { $_->[-1] eq "/bin/sh\n" }
  4.     map { [ $_, ( split ':', $_ )[3,-1] ] } `cat /etc/passwd`;
上述语句是一个典型的"schwartzian transform"。它可以拆分成几步,

1. 把/etc/passwd读到@passwd中
  1. my @passwd = `cat /etc/passwd`;

点击(此处)折叠或打开

  1. @passwd =
  2. (
  3.      "bin:x:2:2:bin:/bin:/bin/sh\n",
  4.      "root:x:0:0:root:/root:/bin/bash\n",
  5.      "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n",
  6.      "sys:x:3:3:sys:/dev:/bin/sh\n",
  7.      ...
  8. )

2. 用@passwd中的数据生成一个新的array,写回@passwd。注意map中的[] - 即新生成的array的每个元素是一个匿名array,每个匿名array中的第一个元素为@passwd的原有元素,后两个元素分别为用冒号劈开后的第三个和最后一个值,即uid和shell。

  1. @passwd = map { [ $_, ( split ':', $_ )[3,-1] ] } @passwd;

点击(此处)折叠或打开

  1. @passwd =
  2. (
  3.     [”bin:x:2:2:bin:/bin:/bin/sh\n", 2, "/bin/sh\n"],
  4.     ['root:x:0:0:root:/root:/bin/bash', 0, '/bin/bash'],
  5.     [“daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n", 1, "/bin/sh\n"],
  6.     [“sys:x:3:3:sys:/dev:/bin/sh\n", 3, "/bin/sh\n"]
  7.     ...
  8. )
3.  筛选出使用bin/sh的用户,写回@passwd。即上述array中最后一个值为"/bin/sh\n"的元素。

  1. @passwd = grep { $_->[-1] eq "/bin/sh\n" } @passwd;

点击(此处)折叠或打开

  1. @passwd =
  2. (
  3.      [”bin:x:2:2:bin:/bin:/bin/sh\n", 2, "/bin/sh\n"],
  4.      [“daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n", 1, "/bin/sh\n"],
  5.      [“sys:x:3:3:sys:/dev:/bin/sh\n", 3, "/bin/sh\n"],
  6.      ...
  7. )

4. 按照uid排序,然后写回@passwd。即按照上述array元素中的第2个值(下标为1)排序。

  1. @passwd = sort { $a->[1] <=> $b->[1] } @passwd;

点击(此处)折叠或打开

  1. @passwd =
  2. (
  3.      [“daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n", 1, "/bin/sh\n"],
  4.      [”bin:x:2:2:bin:/bin:/bin/sh\n", 2, "/bin/sh\n"],
  5.      [“sys:x:3:3:sys:/dev:/bin/sh\n", 3, "/bin/sh\n"],
  6.      ...
  7. )
5. 打印出上述array中的第一个元素(下标为0)

  1. map { print $_->[0] } @passwd;

当然如果你愿意,可以分成上述5个语句来写。只不过是增加了很多临时赋值,且不像是perl的风格。


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