加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Split操作符

发布时间:2020-12-16 00:18:04 所属栏目:大数据 来源:网络整理
导读:作者:半点闲 时间:2013-3-3 13:02 星期日 博客: blog.csdn.net/cg_i 邮箱: b_dx@sohu.com 参考书籍:《 Perl 语言入门 中文版 第六版》 ??? Split 它会根据给定的模式拆分字符串,对于使用制表符、冒号、空白符或任意符号分隔不同字段的字符串来说,用

作者:半点闲
时间:2013-3-3 13:02 星期日
博客:
blog.csdn.net/cg_i
邮箱:
b_dx@sohu.com
参考书籍:《Perl语言入门 中文版 第六版》

??? Split它会根据给定的模式拆分字符串,对于使用制表符、冒号、空白符或任意符号分隔不同字段的字符串来说,用这个操作符分解提取字段相当方便。只要你能将分隔符写成模式(通常是很简单的正则表达式),就可以用Split分解数据。它的用法如下:

??? my @fields = split /separator/,$string;

??? 这里的Split操作符用拆分模式扫描指定的字符串并返回字段(也就是子字符串)列表。期间只要模式在某处匹配成功,该处就是当前字段的结尾、下一字段的开头。所以,任何匹配模式的内容都不会出现在返回字段中。下面就是典型的以冒号作为分隔符的Split模式:

???my @fields = split /:/,“abc:def:g:h”;????????#得到(“abc”,“def”,“g”,“h”)

??? 如果两个分隔符连在一起,就会产生空字段:

???my @fields = split /:/,“abc:def::g:h”;?????#得到(“abc”,“def”,“”,“g”,“h”)

???这里有个规则,它乍看之下很古怪,但很少造成问题:Split会保留开头处的空字段,却舍去结尾处的空字段。例如:

???my @fields = split /:/,“:::a:b:c:::”;????????#得到(“”,“”,“”,“a”,“b”,“c”)

??? 利用Split/s+/模式根据空白符分隔字符也是比较常见的做法。该模式把所有连续空白都视作单个空格并以此切分数据:

??? my $some_input = “This? is a t???? test.n”;

???? my @args = split /s+/,$some_input;?????#得到(“This”,“is”,“a”,“test.”)

??? 默认Split会以空白符分隔$_中的字符串:

??? my @fields = split;???????????????????????#等效于split /s+/,$_;

??? 这几乎就等于以/s+/为模式,只是它会省略开头的空字段。所以,即使该行以空白开头,你也不会在返回列表的开头处看到空字段。若你想以这种方式来分解用空格分隔的字符串,则可以用一个空格来作为模式:split ‘’,$other_string用一个空格来作为模式是split的特殊用法。

??? 一般来说,用在Split中的模式就像之前看到的这样简单。但如果你用到更复杂的模式,请避免在模式里使用捕获圆括号,因为这会启动所谓的“分隔符保留模式(详情请参见Perlfunc文档)。如果需要在模式中使用分组匹配,请在Split里使用非捕获圆括号(?:)的写法,以避免意外。

??? 进一步加深对Split分解提取字段带来的方便。下面给出一段我实际工作中未使用Split操作符分解提取字段的代码(后面还将给出使用Split操作符的代码)对比从中感受一下它的强大:

??? 任务:passwd文件中提取用户名、用户主目录信息;

??? 我们先看一下passwd文件中记录格式(图1-1 部份摘录):

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/sh
……

??? 可以看出每个字段都用冒号(:)进行分隔,以第一条记录从左向右为例我们要提取第一个冒号前面的root(用户名)和第六个冒号前面的/root(用户主目录)。

#代码1.1 未使用Split操作符提取字段代码;
#!/usr/bin/perl -w
use strict;
open (FH,'/etc/passwd') or die "Can't open file: $!";
while (<FH>){
	my ($Pos,$endPos,$length,$Name,$Dir);
	#############
	# 取用户名称
	#############
	$length =  index ($_,":");
	$Name = substr ($_,$length);
	#####################
	# 取用户HOME目录位置
	#####################
	$endPos = rindex ($_,":");
	# $endPos-1跳过当前位置(冒号)
	$Pos = rindex ($_,":",$endPos - 1);		
	# $Pos+1跳过当前位置(冒号) 
	# 查找方向从左向右。所以+1
	$Pos += 1;
	$length = $endPos - $Pos;
	$Dir = substr ($_,$Pos,$length);
		
	print "$Namet$Dirn";
}
close (FH);

??? 程序运行后输出如下(图1-2):

root?????? /root
bin??????? /bin
……

??? 现在我们来分析一下这段代码的算法,提取用户名很简单只需要找到第一个冒号位置通过substr($_,$length)函数返回的子字符串即是需要的用户名。算法比较复杂的部份是提取用户主目录,通过图1-1可见passwd文件本身是有着固定格式的,记录从后向前(从右向左)倒数第二个冒号后面的/root就是用户主目录信息。

??? 提取用户主目录算法思想:

??? 1、? 略过记录最后一个字段;

??? 2、? 找到倒数第二个字段起始位置;

??? 3、? 倒数第一个字段的起始(冒号)位置减去倒数第二个字段字符的开始位置(/号),得出来的结果就是用户主目录字段中的字符长度;

?? 4、? substr($_,$length);返回用户主目录信息;

??? 5、完成。


??? (图 1-3 提取用户目录算法)

??? 总结,通过Perl字符串处理函定位、提取字段信息可以完成我们的任务,可预见当我们要提取多个不相连字段,步骤将更繁琐,代码更长,也更加容易出错,如果,记录各字段位置发生改变,你将不得不重新设计你的算法。

??? 现在,我们再看使用Split操作符分解提取字段的例子:

#代码1.2 使用Split操作符提取字段代码;
#!/usr/bin/perl -w
use strict;
open (FH,'/etc/passwd') or die "Can't open file: $!";
while (<FH>){
  ###########
  # 取用户信息
  ###########	
  my($Name,$Dir) = (split /:/,$_)[0,5];
				
  print "$Namet$Dirn";
}
close (FH);


??? 简单吧my($Name,5]就这么一句。将来,要是还需要提取别的字段,或字段的位置发生改变,只需要给出它所处新的冒号位置即可。

??? 结尾,很高兴你看到这里,我不敢保证文中给的例子是最简便与正确的,但我可以保证的是在写这篇文章的过程中我是快乐的。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读