31

grep函数

(如果你是个的新手,你可以先跳过下面的两段,直接到 Grep vs.loops 样例这一部分,放心,在后面你还会遇到它)

<pre>
grep BLOCK LIST
grep EXPR, LIST
</pre>
grep 函数会用 LIST 中的元素对 BLOCK 或 EXPR 求值,而且会把局部变量 $_ 设置为当前所用的 LIST 中的元素。BLOCK 块是一个或多个由花括号分隔开的Perl 语句,而 List 则是一有序列表。EXPR 是一个或多个变量,操作符,字符,函数,子程序调用的组成的表达式。Grep 会对 BLOCK 块或 EXPR 进行求值,将求值为%{color:red}真%的元素加入到 Grep 返回列表中。如果 BLOCK 块由多个语句组成,那么 Grep 以 BLOCK 中的最后一条语句的求值为准。LIST 可以是一个列表也可以是一个数组。在标量上下文中,grep 返回的是 BLOCK 或 EXPR 求值为真的元素个数。

请避免在 BLOCK 或 EXPR 块中修改 $_ ,因为这会相应的修改 LIST 中元素的值。同时还要避免把 grep 返回的列表做为左值使用,因为这也会修改 LIST 中的元素。(所谓左值变量就是一个在赋值表达式左边的变量)。一些 Perl hackers 可能会利用这个所谓的”特性”,但是我建议你不要使用这种混乱的风格.

grep 与循环

这个例子打印出 myfile 这个文件中含有 terriosm 和 nuclear 的行(大小写不敏感).


open FILE "<myfile" or die "Can't open myfile: $!";
print grep /terrorism|nuclear/i, <FILE>;

对于文件很大的情况,这段代码耗费很多内存。因为 grep 把它的第二个参数作为一个列表上下文看待,所以 < > 操作符返回的是整个的文件。更有效的代码应该这样写:

while ($line = <FILE>) {
if ($line =~ /terrorism|nuclear/i) { print $line }
}

通 过上面可以看到,使用循环可以完成所有 grep 可以完成的工作。那为什么我们还要使用 grep 呢?一个直观的答案是 grep 的风格更像 Perl,而 loops(循环)则是 C 的风格。一个更好的答案是,首先, grep 很直观的告诉读者正在进行的操作是从一串值中选出想要的。其次,grep 比循环简洁。(用工程的说法就是 grep 比循环更具有内聚力)。基本上,如果你对 Perl 不是很熟悉,随便你使用循环。否则,你应该多使用像 grep 这样的强大工具.

计算数组中匹配给定模式的元素个数

在一个标量上下文中,grep 返回的是匹配的元素个数.

$num_apple = grep /^apple$/i, @fruits;
^ 和 $ 匹配符的联合使用指定了只匹配那些以 apple 开头且同时以 apple 结尾的元素。这里 grep 匹配 apple 但是 pineapple 就不匹配。

输出列表中的不同元素

@unique = grep { ++$count{$_} < 2 } 
qw(a b a c d d e f g f h h);
print "@unique\n";

输出结果: a b c d e f g h$count{$_} 是 Perl 散列中的一个元素,是一个键值对 ( Perl中的散列和计算机科学中的哈希表有关系,但不完全相同) 这里 count 散列的键就是输入列表中的各个值,而各键对应的值就是该键是否使 BLOCK 估值为真的次数。当一个值第一次出现的时候 BLOCK 的值被估为真(因为小于2),当该值再次出现的时候就会被估计为假(因为等于或大于2)。

取出列表中出现两次的值


@crops = qw(wheat corn barley rice corn soybean hay 
alfalfa rice hay beets corn hay);
@duplicates = grep { $count{$_} == 2 } 
grep { ++$count{$_} > 1 } @crops;
print "@duplicates\n";

在 grep 的第一个列表元素被传给 BLOCK 或 EXPR 块前,第二个参数被当作列表上下文看待。这意味着,第二个 grep 将在左边的 grep 开始对 BLOCK 进行估值之前完全读入 count 散列。

列出当前目录中的文本文件

@files = grep { -f and -T } glob '* .*';
print "@files\n";

glob 函数是独立于操作系统的,它像 Unix 的 shell 一样对文件的扩展名进行匹配。单个的 * 表示匹配所以当前目录下不以 . 开头的文件, .* 表示匹配当前目录下以 . 开头的所有文件。 -f 和 -T 文件测试符分别用来测试纯文件和文本文件,是的话则返回真。使用 -f and -T 进行测试比单用 -T 进行测试有效,因为如果一个文件没有通过 -f 测试,那么相比 -f 更耗时的 -T 测试就不会进行。

从数组中选出非重复元素

@array = qw(To be or not to be that is the question);
print "@array\n";
@found_words = 
grep { $_ =~ /b|o/i and ++$counts{$_} < 2; } @array;
print "@found_words\n";

输出结果: 
To be or not to be that is the question
To be or not to question

逻辑表达式 $_ =~ /b|o/i 匹配包含有 b 或 o 的元素(不区别大小写)。在这个例子里把匹配操作放在累加前比反过来做有效些。比如,如果左边的表达式是假的,那么右边的表达式子就不会被计算。

选出二维坐标数组中横坐标大于纵坐标的元素

# An array of references to anonymous arrays
@data_points = ( [ 5, 12 ], [ 20, -3 ], 
[ 2, 2 ], [ 13, 20 ] );
@y_gt_x = grep { $_->[0] < $_->[1] } @data_points;
foreach $xy (@y_gt_x) { print "$xy->[0], $xy->[1]\n" }

输出结果: 
5, 12
13, 20

在一个简单数据库中查找餐馆

这个例子里的数据库实现方法不是实际应用中该使用的,但是它说明了使用 grep 函数的时候,只要你的内存够用, BLOCK 块的复杂度基本没有限制。

# @database is array of references to anonymous hashes 
@database = ( 
{ name => "Wild Ginger", 
city => "Seattle",
cuisine => "Asian Thai Chinese Korean Japanese",
expense => 4, 
music => "\0", 
meals => "lunch dinner",
view => "\0", 
smoking => "\0", 
parking => "validated",
rating => 4, 
payment => "MC VISA AMEX", 
},
# { ... }, etc.
);

sub findRestaurants {
my ($database, $query) = @_;
return grep {
$query->{city} ? 
lc($query->{city}) eq lc($_->{city}) : 1 
and $query->{cuisine} ? 
$_->{cuisine} =~ /$query->{cuisine}/i : 1 
and $query->{min_expense} ? 
$_->{expense} >= $query->{min_expense} : 1 
and $query->{max_expense} ? 
$_->{expense} <= $query->{max_expense} : 1 
and $query->{music} ? $_->{music} : 1 
and $query->{music_type} ? 
$_->{music} =~ /$query->{music_type}/i : 1 
and $query->{meals} ? 
$_->{meals} =~ /$query->{meals}/i : 1 
and $query->{view} ? $_->{view} : 1 
and $query->{smoking} ? $_->{smoking} : 1 
and $query->{parking} ? $_->{parking} : 1 
and $query->{min_rating} ? 
$_->{rating} >= $query->{min_rating} : 1 
and $query->{max_rating} ? 
$_->{rating} <= $query->{max_rating} : 1 
and $query->{payment} ? 
$_->{payment} =~ /$query->{payment}/i : 1
} @$database;
}

%query = ( city => 'Seattle', cuisine => 'Asian|Thai' );
@restaurants = findRestaurants(\@database, \%query);
print "$restaurants[0]->{name}\n";

输出结果: Wild Ginger


perl中的grep函数介绍相关推荐

  1. java中正则表达式函数_java正则表达式PHP中的正则表达式函数介绍

    java正则表达式PHP中的正则表达式函数介绍 正则表达式(Regular Expression) 正则表达式系统: 1.POSIX 2.Perl PHP中使用的regex是PCRE: NOTE:PC ...

  2. Numpy中np.mashgri() 函数介绍及2种应用场景

    @[toc](Numpy中np.mashgri() 函数介绍及2种应用场景 文章目录:) 近期在好几个地方都看到meshgrid的使用,虽然之前也注意到meshgrid的用法. 但总觉得印象不深刻,不 ...

  3. bash中的grep函数_如何在Bash中编写函数

    bash中的grep函数 在编程时,实际上是在定义要由计算机执行的过程或例程 . 一个简单的类比将计算机编程与烤面包进行比较:您一次列出了要设置工作环境的成分,然后列出了最终要面包所必须采取的步骤. ...

  4. php spl函数,PHP SPL标准库中的常用函数介绍

    这篇文章主要介绍了PHP SPL标准库中的常用函数介绍,本文着重讲解了spl_autoload_extensions().spl_autoload_register().spl_autoload()三 ...

  5. vba 云服务器,EXCEL服务器中VBA接口函数介绍

    EXCEL服务器中VBA接口函数介绍 日期:2017-11-27 14:40  |  分类:最新资讯  |  人气: EXCEL服务器中VBA接口函数 SaveReport 作用:保存报表模板或者报表 ...

  6. Python中numpy.power()函数介绍

    Python中numpy.power()函数介绍 power(x, y) 函数,计算 x 的 y 次方. 示例: x 和 y 为单个数字: import numpy as npprint(np.pow ...

  7. SQL中的聚合函数介绍

    什么是聚合函数(aggregate function)? 聚合函数对一组值执行计算并返回单一的值. 聚合函数有什么特点? 除了 COUNT 以外,聚合函数忽略空值. 聚合函数经常与 SELECT 语句 ...

  8. SQL中的ISNULL函数介绍

    SQL中有多种多样的函数,下面将为您介绍SQL中的ISNULL函数,包括其语法.注释.返回类型等,供您参考,希望对您学习SQL能够有所帮助. ISNULL 使用指定的替换值替换 NULL. 语法 IS ...

  9. VC++中的WinMain()函数介绍

    WinMain()函数 WinMain()函数等价于控制台程序中的main()函数.该函数是执行开始的地方,也是为程序其余 部分执行基本初始化工作的地方.为了允许 Windows 传递数据,WinMa ...

最新文章

  1. 在控制台输出口,根据内存地址,找到被过度释放的对象!
  2. AUTOSAR从入门到精通100讲(四十七)-车载以太网 SOME/IP-SOME/IP的概念
  3. leetcode 1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
  4. 在libevent中使用线程池
  5. Swift入门基础知识
  6. python中snip_我终于弄懂了Python的装饰器(三)
  7. 计算机视觉实战 (一) 开个视觉实战专栏
  8. php 远程文件是否存在,如何通过php判断本地及远程文件是否存在
  9. unity player 显示播放错误时的解决办法
  10. EXE文件结构及读取方法
  11. python 邮件分类_python_NLP实战之中文垃圾邮件分类
  12. python nonetype iterable_无法解决“NoneType”对象不是iterable类型
  13. 电池SOC仿真系列-基于Simscape搭建的锂电池模型
  14. Java读写csv文件操作
  15. 如何下载jQuery
  16. 基于Java Web的航空售票管理系统(酒店管理系统,图书管理系统、学生管理系统)
  17. springboot的学习(1)
  18. Word长篇文档排版技巧
  19. 有N个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘输入N个学生的数据,要求打印出3门课的总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课成绩)
  20. jQuery实现购物车计算价格统计功能

热门文章

  1. 《与熊共舞》第一章--逆“风”而行
  2. 从2345离职的原因
  3. 打折优惠——循环入门
  4. 对搜狗搜索引擎的评价
  5. 爬虫-requests库(二)get请求参数的使用 —搜狗搜索后爬取搜索结果
  6. python初级6(九九乘法表,二进制,ASCII编码,GBK,unicode,utf-8)
  7. 务实 创业_务实思维:新手与专家
  8. python海龟画小猪佩奇动画片全集_用python画个小猪佩奇
  9. 大数据导论答案_智慧树知到答案大数据导论课后作业答案
  10. 山东财经大学python实验六答案_金融学(山东财经大学)智慧树知道2020章节测验答案...