zoukankan      html  css  js  c++  java
  • Perl语言入门笔记 第九章 用正则表达式处理文本

    =pod
    #第九章:用正则表达式处理文本
    用s///进行替换
    	s///查找替换功能
    	s/Barney/Fred/; #把Barney替换成Fred
    	s/with (w+)/against $1's team/;
    	
    	例子:
    		$_ = "green scaly dinosaur";
    		s/(w+) (w+)/$2, $1/; #替换后为"Scaly, green dinosaur"
    		s/^/huge, /; #替换后为"huge, scaly, green dinosaur"
    		s/,.*een//; #空替换:此时为"huge dinosaur"
    		s/green/red/; #匹配失败:仍为"huge dinosaur"
    		s/w+$/($`!)$&/;	#替换为huge (huge !)dinosaur
    		s/s+(!W+)/$1 /; #替换为"huge (huge!) dinosaur"
    		s/huge/gigantic/; #替换为"gigantic (huge!) dinosaur"
    		
    用/g进行全局替换
    	s///只会一次替换,默认的行为
    	$_ = "home, sweet home!";
    	s/home/cave/g;
    	print "$_
    "; #打印"cave, sweet cave"
    	
    	一个常见的全局替换是缩减空白,也就是将任何连续的空白转换成单一空格:
    	$_ = "Input data	 may have    extra whitespace";
    	s/s+/ /g; #现在它变成了"Input data may have extra whitespace."
    
    	s/^s+//; #将开头的空白替换成空字符串
    	s/s+$//; #将结尾的空白替换成空字符串
    	s/^s+|s+$//g; #去除开头和结尾的空白符,但运行可能会慢,由于perl的引擎问题
    
    不同的定界符:
    	替换时,也可以像m//和qw//一样,我们也可以改变s///的定界符,但由于替换符会用到三个定界符,所以情况又有点不同。
    	s#^https://#http://#
    	s{fred}{barney};
    	s[fred](barney);
    	s<fred>#barney#;
    	
    可用替换修饰符:
    	s#wilma#Wilma#gi; #将所有的WilmA或者WILMA一律替换为Wilma
    	s{__END__.*}; #将__END__标记和它后面的所有内容都删掉
    	
    绑定操作符:
    	$file_name =~ s#^.*/##s; #将$file_name中所有的Unix风格的路径全部去除
    	
    无损替换:
    	如果需要同时保留原始字符串和替换后的字符串,该怎么办?传统的做法是先复制一份拷贝后再替换:
    		my $original = 'Fred ate 1 rib';
    		my $copy = $original;
    		$copy =~ s/d+ ribs?/10 ribs/;
    	替换成一步:
    		(my $copy = $original) =~ s/d+ ribs?/10 ribs/;
    	新写法:
    		use 5.014;
    		my $copy = $original =~ s/d+ ribs?/10 ribs/r; #先做替换,再复制
    
    大小写切换:
    	U:	使目标变为大写
    		$_ = "I saw Barney with Fred.";
    		s/(fred|barney)/U$1/gi; #$_现在成了"I saw barney with fred."
    	L: 使目标变为小写
    		s/(fred|barney)/L$1/gi; #$_现在成了"I saw barney with fred"
    	E: 关闭大小写转换,不然会影响后面的字符
    		s/(w+) with (w+)/U$2E with $1/i; #$_现在成了"I saw FRED with barney"
    	
    	使用小写形式(l与u)时,他们只会影响紧跟其后的第一个字符:
    		s/(fred|barney)/U$1/ig; #$_替换后为"I saw Fred with Barney"
        
        s/(fred|barney)/uL$1/ig; # 第一个字母大写,其它字符小写
        也可以用在双引号的字符串中:
        	print "Hello, Lu$nameE, would you like to play a game?
    "
    
    split操作符:
    	根据给定的模式拆分字符串,对于使用制表符、冒号、空白或任意符号分割不同字段数据的字符串来说,这个操作符分解提取字段相当方便,只要你能将分隔符写成模式,就可以使用split分解数据,它的使用用法如下:
    		my @fields = split /separator/, $string;
    		my @fileds = split/:/, "abc:def:g:h"; #得到("abc", "def". "g", "h")
    	如果两个分隔符连在一起,就会产生空字段:
    		my @fields = split/:/, "abc:def:g:h"; #得到("abc", "def", "", "g", "h")
    		
    以CPAN上的Text::CSV库处理csv文件最好。
    	
    	split会保留开头处的空字段,却会舍弃结尾处的空字段。
    		my @field = split /:/, ":::a:b:c:::"; #得到("", "", "", "a", "b", "c")
    	根据split的/s+/模式根据空白符分隔字段也是比较常见的做法,该模式把所有连续空开都视作单个空格并以此切分数据:
    		my $some_input = "This is a 	     test.
    ";
    		my @args = split /s+/, $some_input; #得到("This", "is", "a", "test.")
    	默认split会以空白符分隔$_中的字符串:
    		my @fields = split; #等效于split /s+/, $_;	
    
    join函数:
    	join函数和split函数恰好相反,他会将这些片段接合成一个字符串。join函数的用法如下:
    		my $result = join /$glue/, @pieces;
    		my $x = join ":", 4, 6, 8, 10, 12; # $x为"4:6:8:10:12"
    		
    列表上下文中的m//:
    	在列表上下文中使用模式匹配操作符(m//)时,如果模式匹配成功,那么返回的是所有捕获变量的列表;如果匹配失败,则会返回空列表:
    		$_ = "Hello there, neighbor!";
    		my($first, $second, $third) = /(S+) (S+) (S+)/;
    		print "$second is my $third
    ";
    		用等号,默认匹配的是$_
    		之前在s///的例子中的/g修饰符同样可以用在m//操作符上,其效果就是让模式能够匹配到字符串中的多个地方。
    		如:my $text = "Fred dropped a 5 ton granite block on Mr.Slate";
    		my @words = ($text =~ /([a-z]+)/ig);
    		print "Result: @words
    ";
    		#打印:fred dropped a ton granite block on Mr. Slate
    		这好比反过来用split:正则模式制定的并非想要去除的部分,反而是要留下的部分。
    		一个字符串变成hash
    		my $data = "Barney Rubble Fred Flintstone Wilma Fllintstone";
    		my %last_name = (data =~ /(W+)s+(w+)/g);
    		
    		
    更强大的正则表达式:
    
    非贪婪量词:
    	/fred.+barney/匹配fred, and braney bowling
    	因为.+是贪婪的会匹配更多的单词,会认为barney单词然后跳过了
    	/fred.+?barney/匹配fred and braney
    	
    	回溯动作,逐个匹配需要的内容
    	CPAN上的模块可以处理HTML或类似的标记语言,使用模块为HTML::Parser
    	
    	贪婪样式:
    		s#<BOLD>(.*)</BOLD>#$1#g;
    	非贪婪样式:
    		s#<BOLD>(.*?)</BOLD>#$1#g;
    	
    	非贪婪样式是在通配符后面加上?,如+?,*?,{5,10}?或者{8, }?, ??
    
    跨行的模式匹配:
    	传统的正则表达式是处理单行文本,perl可以处理任意长度的字符串,其模式匹配自然也可以处理多行文本
    	下面的写法可以表示4行的文本:
    		$_ = "I'm much better 
    than Barney is 
    at bowling, 
    Wilma.
    ";
    	^代表开头,$代表结尾,m代表匹配多行(m可看做multiple lines),
    	如:print "Found 'wilma' at start of line
    " if /^wilma/im;
    	
    	open FILE, $filename or die "Can't open '$filename':$|";
    	my $lines = join '', <FILE>;
    	$lines =~ s/^/$filename: /gm;
    	ps:将整个文件读进一个变量,然后把文件名作为每一行的前缀进行替换。
    	
    一次更新多个文件:
    	下面的程序有问题,待解决:$^I好像并不是这样的用法
    	#!/usr/bin/perl -w
    	use strict;
    	chomp(my $date = `date`); #用了bash shell里的date指令
    	$^I = ".bak"; #能循环找当前文件夹下的文件????
    	while(<>)
    	{
    		s/^Author:.*/Author: Randal L. Schwartz/;
    		s/^phone:.*
    //;
    		s/^Date:.*/Date: $date/;
    		print;
    	}	
    	
    	my $date = localtime;
    	钻石操作符会读取命令行参指定的那些文件,程序的主循环一次会读取,更新及输出一行
    		
    从命令行直接编辑:
    	假设你需要更新上百个文件,把里面拼错成Randall的名字改成只有一个l的Randal。你可以写个和之前类似的程序完成此事,或者在命令行上使用如下单行程序一步完成。
    		$perl -p -i.bak -w -e 's/Randall/Randal/g' fred*.dat
    			
    =cut


  • 相关阅读:
    Docker+Nginx 部署Vue+Element前端项目
    MySql取字段逗号分隔的第一个
    Mysql数据库中从表字段中存储了主表以逗号隔开的主键ID,现需求查询从表数据以及以逗号隔开的字段改为主表名称隔开(group_count() find_in_set())
    IIS 错误500.21解决方法
    IIS 出现500.19 错误处理解决方式
    Linux中vim的三种模式
    Centos7 .Net Core 使用Supervisor守护进程,进行后台运行
    Nginx反代理ASP.NET Core项目
    C# vb .net实现圆角矩形特效滤镜
    C# vb .net实现旋转特效滤镜
  • 原文地址:https://www.cnblogs.com/v-BigdoG-v/p/7398615.html
Copyright © 2011-2022 走看看