阅读笔记-精通正则表达式-第2章-入门示例及扩展-1

1. 温度转化的示例

    这一章的开始就介绍了Perl,并且使用Perl中的正则表达式,不断的加强一个温度转化的程序的功能。
    这里直接上完整的示例了:   

print   " Enter a temperature (e.g., 32F, 100C):\n " ;
$input   =   < STDIN > ;     #  接收用户输入的一行文本
chomp ( $input );        #  去掉$input尾部的换行符
if $input   =~  m /^\ s * ([ -+ ] ? [ 0 - 9 ] + ( \. [ 0 - 9 ] + ) ? ) \ s * ([C , F]) \ s * $ / i ) {
  
#  $1保存了整体数值,$2保存了小数部分,S3保存了C或者F
   $inputNum   =  $ 1 ;
  
$type   =  $ 3 ;
  
if ( $type  =~ m/c/i) { # 如果是C或者c
     $celsius   =   $inputNum
    
$fahrenheit   =  ( $celsius   *   9   /   5 +   32 ;
  } 
else  {  #  如果不是C也不是c
     $fahrenheit   =   $inputNum ;
    
$celsius   =  ( $fahrenheit   -   32 *   5   /   9 ;
  }
  
printf   " %.2f C is %.2f F\n " ,   $celsius ,   $fahrenheit ;
else  {  # 匹配失败了
   print   " Expecting a number followed by \"C\" or \"F\",\n " ;
  
print   " so I don't understand \"$input\".\n " ;
}

    重点解释一下这行代码:$input =~ m/^\s*([-+]?[0-9]+(\.[0-9]+)?)\s*([C,F])\s*$/

    $input是一个变量

    =~ 表示匹配的意思

    m/ ... / 表示内部是一个正则表达式

    m/ ... /i表示匹配的正则表达式不区分大小写

    \s表示空白字符,包括空格,制表符,换行符,回车符。

    配的逻辑:行起始,任意多个空白字符,零个或者一个[-+],一个或者多个数字,小数部分,任意多个空白字符,一个C或者一个F,任意多个空白字符行结束。
    这个例子中,比较重要的就是,匹配一个字符串,并且能够记录其中匹配的部分,即$1,$2,$3记录正则表达式中的三个括号内容匹配到的信息。实际中,只是用了 $1,$3,$2没有用到,可是使用非捕获型括号,(?:···)。这样的话,$2就能够保存以前$3中的信息了。

2. Perl安装试用

    此前没用过PERL,虽然上面的代码是书中给出的,总有实际用Perl跑一下,因此下面简单说说我下载并且使用PERL的经历。
    首先,找到PERL的官方网站:http://www.perl.org/
    然后,下载对应操作系统的PERL二进制安装包:http://strawberryperl.com/,下载的是5.12.3.0这个版本,40MB的文件,strawberry-perl-5.12.3.0.msi。
    接着,双击strawberry-perl-5.12.3.0.msi这个文件。注意:安装的目录不能有空格,默认安装目录为"C\strawberry\"
    接着,在桌面上新建一个文件,命名为HelloWorld.pl,使用记事本方式打开这个文件,输入一下代码,并保存文件。

print   " Hello,World! It's my first time to use the perl language! " ;
$input   =   < STDIN > ;

    接着,双击桌面上这个文件,得到如下运行结果:

   
    最后,在窗口中,回车,该窗口就会退出了。$input = <STDIN>;就是接收一行字符,否则程序一闪就过去了,看不清输出内容。
    总体来说,如果用两个字来形容PERL,就是简单,用一个字来形容就是爽。没有IDE的启动,没有编译过程,没有各种警告与错误的提示。双击文件就运行。
    最后,将温度转化的代码使用PERL实际运行了一下,保证代码确实能够正常运行。

3. 知识总结

    ·Perl用$variable =~ m/regex/来判断一个正则表达式regex是否匹配某个字符串variable,如果匹配成功,返回true,否则返回false。
    ·相关减记法
     \t   制表符
     \n  换行符
     \r   回车符
     \s  任何空白字符(包括:空格符,制表符,回车符,换行符)
     \S  除\s之外的任何字符
     \w [a-zA-Z0-9]
     \W 除\w之外的任何字符,也就是[^a-zA-Z0-9]
     \d  [0-9],即数字
     \D  除\d外的任何字符,即[^0-9]
    ·/i 表示此次匹配不区分大小写
    ·(?:···) 这个麻烦的写法可以用来分组文本,但并不捕获
    ·匹配成功之后,Perl可以用$1,$2,$3之类的变量来保存相对应的(···)括号内的子表达式匹配的文本。使用这些变量,我们能够用正则表达式从字符串中提取信息。

4. 使用正则表达式修改文本

    匹配字符串的格式:variable =~ m/regex/
    修改字符串的格式:variable =~ s/regex/replacement/
    几个使用regex修改文本的例子:

    4.1 公函生成程序
    假设有一个公函系统,它包含很多公函模板,其中有一些标记,对每一封具体的公函来说,标记部分的值可以定制,这个定制的就是通过使用正则来修改标记部分来实现的。
    模板:
    Dear =FIRST=,
    You have been chosen to win a brand new =TRINKET=! Free!
    Could you use another =TRINKET= in the =FAMILY= household?
    Yes =SUCKER=, I bet you could! Just respond by......
    定制:
    $given = "Tom";
    $family = "Cruise";
    $wunderprize = "100% genuine faux diamond";
    填写模板
    $letter =~ s/=FIRST=/$given/g;
    $letter =~ s/=FAMILY=/$famliy/g;
    $letter =~ s/=SUCKER=/$given $family/g;
    $letter =~ s/=TRINKET=/fabulous $wunderprize/g;
    这里的/g是“全局替换”的修饰符。它告诉s/···/···/在第一次替换完成之后继续搜索更多的匹配文本,进行更多的替换。

    4.2 修正股票价格

     对于"9.0500000037272",希望得到的形式可能是"9.05"。假设:要求是保留小数点后两位数字,如果第三位不为零,也要保留。
     $price =~ s/(小数点  小数部分的前两位   不为零的小数部分的第三位) 小数部分分的其他位/$1/
     $price =~ s/(\.\d\d[1-9]?)\d*/$1/
     注意:此处直接匹配的是小数点开始的部分,小数点起到了开始点的作用。没有直接去匹配整体的数字,如果整体匹配的话,反而会变得更加麻烦。这个例子的问题本身就是针对可能存在的小数部分进行修正,因此直接匹配小数部分更加合理。

    4.3 处理邮件的小工具

    要求编写一个名为mkreply的程序,从king.in中的邮件信息文件中,解析出邮件头部的一些字段:日期,主题等。把解析出的字段保存到king.out上面。
    输入文本,king.in:    

From elvis Thu Feb  29   11 : 15   2007
Received
:  from elvis @localhost  by tabloid . org ( 8.11 . 3 ) id HA8CMY
Received
:  from tabloid . org by gateway . net ( 8.12 . 5 / 2 ) id N8XBK
To
:  jfriedl @regex . info (Jeffrey Friedl)
From
:  Elvis @tabloid . org (The King)
Date
:  Thu ,  Feb  29   2007   11 : 15
Message
- Id :   < 2007022939939 . KA8CMY @tabloid . org >
Subject
:  Be seein '  ya around
Reply-To: elvis@hh.tabloid.org
X-Mailer: Madam Zelda
' s Psychic Orb [version  3.7  PL92]

Sorry I haven
' t been around lately. A few years back I checked 
into that ole heartbreak hotel in the sky, ifyaknowwhatImean.
The Duke says "hi".
        Elvis

    输出文本,King.out:

To :  elvis @hh . tabloid . org (The King)
From
:  jfriedl @regex . info (Jeffrey Friedl)
Subject
:  Re :  Be seein '  ya around

On Thu, Feb 29 2007 11:15 The King wrote:
|> Sorry I haven
' t been around lately .  A few years back I checked 
|>  into that ole heartbreak hotel in the sky ,  ifyaknowwhatImean .
|>  The Duke says  " hi " .
|>          Elvis

    perl的命令行格式:%perl  -w  mkreply  king.in  >  king.out
    其中,-w用来打开Perl的额外警告功能。
    mkreply的完整代码    

open (InFile ,   " $ARGV[0] " ) or  die   " open in file fail " ;
open (OutFile ,   " >$ARGV[1] " ) or  die   " open out file fail " ;

while ( $line   =   < InFile > ) {
  
if ( $line   =~  m /^\ s * $ / ) {  #  如果存在空行
     last #  就立即结束while循环
  }
  
if ( $line   =~  m /^ Subject :  ( .* ) / i) {  #  "Subject: Be seein' ya around"
     $subject   =  $ 1 ;
  }
  
if ( $line   =~  m /^ Date :  ( .* ) / i) {  #  "Date: Thu, Feb 29 2007 11:15"
     $date   =  $ 1 ;
  }
  
if ( $line   =~  m /^ Reply - To :  ( \ S + ) / i) {  #  "Reply-To: elvis@hh.tabloid.org"
     $reply_address   =  $ 1 ;
  }
  
if ( $line   =~  m /^ From :  ( \ S + \ (([ ^ ()] * ) \ ) / i) {  #  "From: Elvis@tabloid.org (The King)"
     $reply_address   =  $ 1 ;
    
$from_name   =  $ 2 ;
  }
}

if ( not  defined ( $reply_address ) ) {
  
die   " couldn't glean the required information! reply_address. " ;
}

if ( not  defined ( $from_name ) ) {
  
die   " couldn't glean the required information! from_name. "
}
if ( not  defined ( $subject ) ) {
  
die   " couldn't glean the required information! subject. " ;
}
if ( not  defined ( $date ) ) {
  
die   " couldn't glean the required information! date. " ;
}

print  OutFile ( " To: $reply_address ($from_name)\n " );
print  OutFile ( " From: jfriedl\@regex.info (Jeffrey Friedl)\n " );
print  OutFile ( " Subject: Re: $subject\n " );
print  OutFile ( " \n " );
print  OutFile ( " On $date $from_name wrote:\n " );
while ( $line   =   < InFile > ) {
  
print  OutFile ( " |> $line " );
}

close (InFile);
close (OutFile);

    说明几点:
    ·书上的程序代码我没有调通,读文件还行,写文件好像有问题,直接修改了读写文件的方式。
      命令行格式为:%perl -w mkreply.pl king.in king.out
      Perl的命令行格式为 %perl   my.pl   $ARGV[0]   $ARGV[1]
    ·书中的程序中,有两处关于\s的使用错误了。     
      ($line =~ m/^Reply-To: (\S+)/i) 
   
   ($line =~ m/^From: (\S+\(([^()]*)\)/i)
      这两行中的(\S+)是匹配连续的非空白字符,书中误写为了(\s+)。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值