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

perl处理文本经验积累

发布时间:2020-12-15 23:46:58 所属栏目:大数据 来源:网络整理
导读:1. 把同根路径不同文件包中同名的文件合并 ?例子: ?作用描述:? 问题: 现有五个目录?分别存放5个领域的文件 F:/.../fold/canyin/sys F:/.../fold/jiaotong/sys F:/.../fold/lvyou/sys F:/.../fold/shangwu/sys F:/.../fold/tiyu/sys 而每个 F:/.../fold/xxx/

1. 把同根路径不同文件包中同名的文件合并

?例子:

?作用描述:? 问题:
现有五个目录?分别存放5个领域的文件
F:/.../fold/canyin/sys
F:/.../fold/jiaotong/sys
F:/.../fold/lvyou/sys
F:/.../fold/shangwu/sys
F:/.../fold/tiyu/sys

而每个
F:/.../fold/xxx/sys目录
下面有
18个文件:
text(0).txt
text(1).txt
....
text(16).txt
text(17).txt

想把五个领域目录下的文件名相同的文件合并成一个文件

比如:
all_text(0).txt?=?
(F:/.../fold/canyin/sys/text(0).txt)?
+?(F:/.../fold/jiaotong/sys/text(0).txt)
+?(F:/.../fold/lvyou/sys/text(0).txt)?
+?(F:/.../fold/shangwu/sys/text(0).txt)
+?(F:/.../fold/tiyu/sys/text(0).txt)
这里的'+'?表示文件合并的意思
即后面处于不同目录下面的五个同名文件将被合并到all_text(0).txt文件中

#!
@person=qw(canyin jiaotong lvyou shangwu tiyu);
for($i=0;$i<18;$i++) {
??????? $src=join('+',map{$_."//sys//test_part_result_by_index($i).txt"} @person);
??????? print $src,"/n";
??????? system("copy $src fold1_all_text($i).txt");
}

2. 简易获取当前目录下所有文件名

?一般是用CWD模块,下面这个更简洁

#!
#####
#给目录下面的文件改名字
while($file=glob('*.txt')) {#glob 取得当前目录下的文件名
??????? print "$file/n";
??????? $newfile = "canyin_".$file;
??????? rename($file,$newfile);
??????? print "$newfile/n";
}

3. 去除文件每行前标号

在EBMT翻译时,为防止串行一般在每行前加标号,格式如:[0001234]

在评测前,需要去掉之,代码如下:? 写成批处理即可运行。

#!?????????????????????????????????????????
$inputfile? =shift ;
$outputfile = shift;
open IN,"<$inputfile" or die "can not open file : $inputfile/n";
open OUT,">$outputfile" or die "can not open file : $outputfile/n";
foreach $str (<IN>){

$str =~s/^/[( /d+ )/]//g;#去掉行首[ 12121212 ]
$str =~s/^ //g;#去掉行首空格
print OUT $str;
}

4. 从评测结果文件中提取结果:

#!

$inputfile = shift;

$outputfile = shift;
open IN,$inputfile or die "can not open file,$!/n ";
open OUT,">$outputfile" or die"can not open >out.txt,$!/n";

my $contents = <IN>;
my @system_names;
$sys = "system name= /"";
$nist5 = "Nist5Score=/"";
$bleu5 = "Bleu5Score=/"";
my @nist5score;
my @nist3score;
my @nist1score;
my @bleu5score;
my @bleu3score;
my @bleu3score;
#@system_names?= /$sys(.*?)/"/g;
$sys ="<system name=/"";

@system_names=($contents=~/$sys(.*?)/"/gs);
@nist5score = ($contents=~/$nist5(.*?)/"/gs);
@bleu5score = ($contents=~/$bleu5(.*?)/"/gs);
print OUT join("/n",@system_names);
print OUT "/nnist5/n";
print OUT join("/n",@nist5score);
print OUT "/nbleu5/n";
print OUT join("/n",@bleu5score);
5。把文件随机化

#!/usr/bin/perl
#功能: 把输入文件随机化(每行是一个单位)
#方法:每次产生一个在总行数之间的随机整数,用一个标记数组看有是否已经输出。

use strict;
my $n = 100;
my $seed = 1;
#Do not call srand() (i.e. without an argument) more than once in
#a script. The internal state of the random number generator
#should contain more entropy than can be provided by any seed,so
#calling srand() again actually *loses* randomness.

my $infile = shift;
my $outfile = shift;
open(IN,$infile) || die "无法打开input.txt/n";
open (OUT,">$outfile")|| die "无法打开output.txt/n";

my @all = <IN>;
my $sen_num = @all;#总句子数
my $cur_num = 0;#目前提取的句数
my @lab ;#标记数组
my $selected = 100;
my $non_selected = 0;

srand();?

#先把标记数组初始化
my $i=0;
for($i=0;$i<@all;$i++)
{
?$lab[$i] = $non_selected;
}

my $num = 0;
while($cur_num < $sen_num)
{
? $num = int rand($sen_num);
??
? if($lab[$num] != $selected)
? {
? ?print OUT @all[$num];
? ?
? ?$lab[$num] = $selected;
? ?$cur_num ++;
? ?#$num ++;
? }
}

6. 上面的随机做法效率很低,建议用下面这个很棒的shuffle做法。

#!
use List::Util 'shuffle';
@all = <STDIN>;
$num = @all;
@list = (0..$num-1);
@shuffled = shuffle(@list);
foreach $i(@shuffled){
?print $all[$i];
?}

7. 文件成行读入?
?? 把一个文件读入一个字符串
方法:
?my $contents;
{
? local $/;
? $contents = <IN>;
}

my $contents = do {local $/; <IN>}
例子: 文件中以空行为语块分割的标记,把语块内部顺序保留,而语块间逆序输出。
#!
open IN,"input.txt";
open OUT,">output.txt";
my $contents;
{
? local $/;
? $contents = <IN>;
}
my @all = split("/n/n",$contents);#不同文件格式也可能是my @all = split("/n/r/n",$contents);
for(my?$i=@all-1;$i>=0;$i--)
{
? print OUT $all[$i],"/n/n";
}
close(IN);
close(OUT);

8. 如何用foreach每次读取多句?
? 那就用<FH>读三次,
while (!eof(FH)){
$line1 = <FH>;
$line2 = <FH>;
$line3 = <FH>;
...
}

9 (非)贪婪(non-greedy)匹配

? 当该字符紧跟在任何一个其他限制符 (*,+,?,{n},{n,},m}) 后面时,
匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,
而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
例如,对于字符串 "oooo",’o+?’ 将匹配单个"o",而 ’o+’ 将匹配所有 ’o’。

如果你使用一个旧的Perl版本,并且你不想贪婪匹配,你必须使用否定的字符类。(真的,你正在得到一种限制的贪婪匹配)

在Perl的现在版本中,你能通过在数量词后使用一个问号,?
强迫进行非贪婪的最小匹配。 
同样的用户名匹配将是/.*?:/。现在这个.*?将尽可能匹配少的字符,而不是尽可能多的字符,?
所以它停在第一个冒号而不是最后一个冒号。

例子:
问题是这样的:
比如给一句话,形式如下:
I(i)/xx came(come)/xx,(,)/xx ((()/xx {({)/xx how it like(how it like)/yy?
解释格式:
词组,然后是用小括号包围的词组还原形式,然后是斜杠'/',然后是词性..

要求: 把还原形式去掉
例如上句想得到:
I/xx came/xx,/xx (/xx {/xx how it like/yy

难点: 1. 词组可能是左小括号'(' 即可能有词组:? ((()/xx
????? 2. 各种标点,括号() [] {}等
????? 3. 好几个词的词组,如: How it like(how it like)/xx

做法: 拆分成一段一段来做吧,要不然用regexp处理各段之间的混淆很麻烦:

my $str="I(i)/xx came(come)/xx,)/xx ((()/xx )())/x {({)/xx how it like(how it like)/yy"; my $res=''; while($str=~m|(.*?//S+)|g) {# 非贪婪匹配,否则结果就是 I/yy ??????? my $token=$1; ??????? $token=~s|/(/(/(/)|/(|g; ??????? $token=~s|/)/(/)/)|/)|g; ??????? $token=~s|/(.*/)||g; ??????? $res.=$token; } print $res,"/n";

(编辑:李大同)

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

    推荐文章
      热点阅读