Perl Learning 8 Processing Text with Regular Expression

用s///进行替换:如果把m//模式匹配(pattern match)想象成文字处理器的“查找”功能,那么s///替换(substitution)操作符就是“查找并替换”功能。此操作符只是把存在变量中匹配模式的那部分内容替换成另一个字符串:

<span style="font-size:18px;">$_ = "He's out bowling with Barney tonigth.";
s/Barney/Fred/; #replacing Barney with Fred
print "$_\n";</span>

如果匹配失败,则什么事都不会发生,变量也不会受影响。当然,模式字符串与替换字符串还可以更加复杂。下面的替换字符串用到了第一个捕获的变量,也就是$1,模式匹配时会对它赋值:

<span style="font-size:18px;">s/with (\w+)/against $1's team/;
print "$_\n"; #print “He’s out bowling against Fred’s team tonight.”</span>

S///返回的是布尔值,替换成功时为真,否则为假。

用/g进行全局替换,s///只会进行一次替换,/g修饰符可以让s///进行所有可能的,不重复的替换:

<span style="font-size:18px;">$_ = “home, sweet home !”;
s/home/cave/g;
print “$_\n”; #print “cave, sweet cave!”</span>

一个相当常见的全局替换就是缩减空白,也就是将任何连续的空白转换为单一空格:

<span style="font-size:18px;">$_ = “Input   data\t may have    extra whitespace.”;
s/\s+/ /g; #”Input data may have extra whitespace.”</span>

大小写替换:\U转义符会将其后的所有字符转换成大写的:

<span style="font-size:18px;">$_ = “I saw Barney with Fred.”;
s/(fred|barney)/\U$1/gi; # “I saw BARNEY with FRED.”</span>

类似地,\L转义符会将它后面的所有字符转换成小写的。默认情况下,它们会影响之后全部的(替换)字符串。你也可以用\E关闭大小写转换的功能:

<span style="font-size:18px;">s/(\w+) with (\w+)/\U$2\E with $1/i;  #”I saw FRED with Barney.”</span>

split操作符,用法:my @fields = split /separator/, $string;

这里的split操作符用拆分模式扫描指定的字符串并返回字段(也就是子字符串)列表。期间只要模式在某处匹配成功,该处就是当前字段的结尾、下一个字段的开头。split会保留开头处的空字段,却会舍弃结尾处的空字段。

默认split会以空白符分隔$_中的字符串: my @fields = split; # split /\s+/, $_;

join函数不会使用模式,它的功能与split恰好相反。用法: my $result = join $glue, @pieces; 我们可以把join的第一个参数理解为胶水,它可以是任意字符串。其余参数则是一串片段。join会把胶水涂进每个片段之间并返回结果字符串:

my $x = join “:”, 4,6, 8, 10, 12; # $x为”4:6:8:10:12”

所以说,列表至少要有两个元素,否则胶水无法涂进去。

列表上下文中的m//,在使用split时,模式指定的只是分隔符:分解得到的字段未必就是我们需要的数据。有时候,指定想要留下的部分反而比较简单。之前在s///的例子中看到的/g修饰符同样也可以用在m//操作符上,其效果就是让模式能够匹配到字符串中的多个地方。

<span style="font-size:18px;">my $text = “Fred dropped a 5 ton granite block on Mr. Slate”;
my @words = ($text =~/([a-z]+)/ig);
print “Result: @words\n”;
# print : Fred dropped a ton granite block on Mr Slate</span>

这就好比是反过来用split:正则模式指定的并非想要去除的部分,反而是要留下的部分。

事实上,如果模式中有多组圆括号,那么每次匹配就能捕获多个字符串。假设我们想把一个字符串变成哈希,就可以这样做:

my $data = “Barney Rubble Fred Flintstone Wilma Flintstone”;
 my %last_name = ($data =~ /(\w+)\s+(\w+)/g);

每次模式匹配成功就会返回一对被捕获的值,而这一对值正好成为新哈希的键值对。

非贪婪量词。正则表达式引擎一直进行回溯动作,不断地以不同的方式调整模式匹配的内容来适应字符串,直到最终找到一个整体匹配成功的为止,要是直到最后都找不到就宣告失败。

跨行的模式匹配, ^和$都是代表整个字符串的开头和结尾的锚位。但当模式加上/m修饰符之后,就可以用它们匹配字符串内的每一行,这样一来,它们代表的位置就不再是整个字符串的头尾,而是每行的开头跟结尾了。接下来的程序会先把整个文件读进一个变量,然后把文件名作为每一行的前缀进行替换:

<span style="font-size:18px;">$fliename = "hsl.txt";
open FILE, $fliename
or die "Can't open '$fliename' : $!";
my $lines = join '',<FILE>;
$lines =~s/^/$fliename: /gm;
print $lines;</span>

一次更新多个文件:通过程序自动更新文件内容时,最常见的做法就是先打开一个和原来内容一致的新文件,然后在需要的位置进行改写,最后把修改后的内容写进去。

现在有个叫做fred03.dat的文件内容如下:

需要改为:

简单的说,我们需要作出三项改动:Author字段的姓名要改,Date要改为今天的日期,而Phone要删除。

<span style="font-size:18px;">#!/usr/bin/perl -w
use strict;
chomp(my $date = localtime);
$^I = "f.bak";
while(<>){
s/^Author:.*/Author: Randal L. Schwartz/;
s/^Phone:.*\n//;
s/^Date:.*/Date: $date/;
print;
}</span>

在命令行中输入:perl change.pl fred03.dat

先假设钻石操作符正好打开了文件fred03.dat。除了像以前一样打开文件之外,他还会把文件名改为fred03.dat.bak。虽然打开的是同一个文件,但是它在磁盘上的文件名已经不同了。接着,钻石操作符会打开一个新文件并将它取名为fred03.dat。这么做并不会有任何问题,因为我们已经没有同名文件了。现在钻石操作符会把默认的输出设定为这个新打开的文件,所以输出来的所有内容都会被写进这个文件。

习题:

1.我的:

<span style="font-size:18px;">use strict;
chomp(my $what = <STDIN>);
print "$what" x 3;</span>

答案:/($what){3}/表示没有看懂

2

<span style="font-size:18px;">my $in = $ARGV[0];
if(! defined $in){
die "Usage:$0 filename";
}
my $out = $in;
$out = ~s/(\.\w+)?$/.out/;
if(! open $in_fh, '<',$in){
die "Can't open '$in':$!";
}
if(! open $out_fh, '>',$in){
die "Can't open '$out':$!";
}
while(<$in_fh>){
s/Fred/Larry/gi;
print $out_fh $_;
}</span>

此程序一开始会先清点它的命令行参数,预期应该要一个。

3

<span style="font-size:18px;">my $in = $ARGV[0];
if(! defined $in){
die "Usage:$0 filename";
}
my $out = $in;
$out = ~s/(\.\w+)?$/.out/;
if(! open $in_fh, '<',$in){
die "Can't open '$in':$!";
}
if(! open $out_fh, '>',$in){
die "Can't open '$out':$!";
}
while(<$in_fh>){
chomp;
s/Fred/Larry/gi;
s/Wilma/Fred/gi;
s/\n/Wilma/g;
print $out_fh “$_\n”;
}</span>

我们必须先找到一个“占位符”,而且必须是不会出现在数据中的。因为使用了chomp,所以我们知道换行符(\n)是绝对不会出现在字符串中的,所以换行符就可以充当占位符。

4

<span style="font-size:18px;">$^I = ".bak";
while(<>){
if(/\A#!/){
$_.="##Copyright (C) 2015 by HSL\n";
}
print;
}</span>

5.为避免重复加上版权声明,我们得分两回处理所有文件。第一回,我们会先建立一个哈希,它的键是文件名称,而它的值是什么并不重要。为了简单起见,设为1。第二回,我们会把这个哈希当成待办事项列表逐个处理,并把已经包含版权声明行的文件移除。目前正在读取的文件名称可用$ARGV取得,所以可以直接把它拿来当哈希键。

<span style="font-size:18px;">my %do_these;
foreach(@ARGV){
$do_these{$_} = 1;
}
while(<>){
if(/\A## Copyright/){
delete $do_these{$ARGV};
}
}
@ARGV = sort keys %do_these;
$_I = ".bak";
while(<>){
if(/\A#!/){
$_ = "## Copyright (c) 2015 by HSL";
}
print;</span>

这一章节让我更加深入地了解了如何用perl对文件进行操作。与此同时,我正在继续看我的VTR-to-Bitstream项目,其中在将Virtex-6改为ZYNQ遇到了不少的问题。不过正在和老师商讨如何攻克。也开始着手看一些关于可重构计算的书了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 03:32:39

Perl Learning 8 Processing Text with Regular Expression的相关文章

regular expression, grep (python, linux)

https://docs.python.org/2/library/re.html re.match(pattern, string, flags=0)  尝试从字符串的起始位置匹配一个模式 re.search(pattern, string, flags=0)  扫描整个字符串并返回第一个成功的匹配 re.sub(pattern, repl, string, max=0)  替换字符串中的匹配项 >>> import re >>> s='112.90.239.137 

Python正则表达式 re(regular expression)

1. 点. .: 代表一个字符 (这个跟linux的正则表达式是不同的,那里.代表的是后面字符的一次或0次出现) 2. 转义 \\ 或者 r'\': 如 r'python\.org' (对.符号的转义) 3. ^ 非或叫做排除 如[^abc]: 任何以非a,b,c的字符 4. | 选择符 如python|perl (从python和perl选择一个) 也可以: p(ython|erl) 5. ? 可选项 如: r'(http://)?(www\.)?python\.org' (http://和w

Regular Expression(正则表达式)之邮箱验证

正则表达式(regular expression, 常常缩写为RegExp) 是一种用特殊符号编写的模式,描述一个或多个文本字符串.使用正则表达式匹配文本的模式,这样脚本就可以轻松的识别和操作文本.其实,正则表达式是值得大家花时间学习的.正则表达式不仅在javaScript 中有用,在其他许多地方也可以使用正则表达式,例如其他编程语言(比如Perl,Java,C#,Python 和PHP ),Apache 配置文件以及BBEdit 和TextMate 等文本编辑器.甚至Adobe Dreamwe

Regular Expression 学习笔记

原文地址:https://swtch.com/~src/regexp/regexp1.html Regular Expression Matching Can Be Simple And Fast 正则表达 正则表达式是一个用于描述一组字符串的标记.当一个特定的字符串是在被正则表达式所描述的组合时,我们经常说正则表达式匹配这个字符串. 最简单的正则表达式是一串简单的原义的字符串.除了特殊的元字符*+?(),字符串会匹配他们自身.为了匹配元字符,用转义字符\来避免它,:\+匹配一个原义的加号. 两

[label][翻译][JavaScript Regular Expression]JavaScript Regular Expressions

原文:http://www.javascriptkit.com/javatutors/re.shtml 校验用户的输入是每一个软件开发者的必须要做的事情. 正则表达式与模式 如何在JavaScript中使用正则表达式呢?这里有两种方式: 1)字面量语法. 2)当你需要动态构建正则表达式时,可以通过RegExp()构造函数. 字面量语法如下: var RegularExpression = /pattern/; RegExp()构造函数方法如下: var RegularExpression = n

Regular Expression Basic

1. Basic Regular Expression a. "^"     matching the head of a line. "^" must be the first character in a regular expression ,else it only a common character. b. "$" matching the end of a line. "$" must be the last c

[转载]正则表达式参考文档 - Regular Expression Syntax Reference.

正则表达式参考文档 - Regular Expression Syntax Reference. [原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref.htm] 引言 正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征.比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征.

Regular Expression Extractor (转)

Regular Expression Extractor是JMeter中的另一个概念—Post-processor,它的作用是得到HTTP响应后,对结果(比如一个html标签页面的内容或json输出数据等)进行处理,通过regular expression抽取字符值,存成一个变量给后面的Sampler使用. 例如在Click Table(afterSelectTable_ajax.action)这个Sampler执行完一次HTTP Request之后得到如下的HTTP Response(一个js

C#中【正则表达式regular expression】相关的知识

Regex System.Text.RegularExpressions.Regex      regex应该是regular expression的缩写 https://msdn.microsoft.com/zh-cn/library/system.text.regularexpressions.regex(v=vs.110).aspx Represents an immutable regular expression.[immutable 不可变的] 代表了不可变的正则表达式 The Re