我有以下用例,输入文件中的输入为:
Line1 : AA BB CC DD EE
我想用
替换它1 2 3 4 5
输出
Line1: 1 2 3 4 5
在Perl的一个正则表达式中,我可以这样做吗
我正在尝试这个但是不成功
my @arr1 = ("AA", "BB", "CC", "DD", "EE");
open F2, $file;
my $count = 0;
while (<F2>) {
my $str = $_;
$str =~ s/$arr[$count]/$count+1/g;
print to file
}
close(F2);
这不是任何想法的伎俩
答案 0 :(得分:2)
如果我理解正确,你想用数字替换每个单词(每个单词后加1)。这是带有测试的程序:
#!/usr/bin/perl
use strict;
use warnings;
use Test::More qw(no_plan);
sub replace {
my $str=shift;
my $count=1;
$str=~s/\w+/$count++/ge;
return $str;
}
is(replace('AA AA DD EE'),'1 2 3 4');
is(replace('A B C D E'),'1 2 3 4 5');
答案 1 :(得分:2)
您需要做一些事情来修改您当前没有执行的文件。最简单的选择是使用File::Inplace(或输出到第二个文件)。
此外,您不是在数组上循环,而是在文件的行上循环,因此它将在每行上仅替换$ arr [0]为1。
use strict;
use warnings;
use File::Inplace;
my @replacees = ("AA", "BB", "CC", "DD", "EE");
my $editor = new File::Inplace(file => "file.txt", regex => "\n");
while (my ($line) = $editor->next_line) {
my $count = 1
for my $replacee (@replacees) {
if ($line =~ m/$replacee/) {
$line =~ s/$replacee/$count/g;
}
$count = $count + 1;
}
$editor->replace_line($line);
}
$editor->commit;
答案 2 :(得分:2)
至于写入同一档案,请注意Vinko的回答。至于替换字符串,请查看以下代码段:
my @arr1 = ("AA", "BB", "CC", "DD", "EE");
my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1);
my $regexp = join( '|', sort { length($b) <=> length($a) } @arr1);
open F2, $file;
while (<F2>) {
my $str = $_;
$str =~ s/($regexp)/$replacements{$1}/ge;
print $str;
}
close(F2);
重要部分:
my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1);
使用@ arr1中的键构建哈希值,值是@ arr1中给定值的索引,加1。
例如,对于@ arr1 =(“a”,“b”,“d”,“c”); %替换将是:(“a”=&gt; 1,“b”,=&gt; 2,“c”=&gt; 4,“d”=&gt; 3);
my $regexp = join( '|', sort { length($b) <=> length($a) } @arr1);
这构建了基本正则表达式,用于查找@ arr1中的所有单词。排序部分按其长度递减来排序单词。所以,对于@ arr1 =(“a”,“ba”,“bac”),$ regexp将是'bac | ba | a'。
这种排序很重要,否则如果任何单词都是任何其他单词的前缀(如我的例子中的“ba”和“bac”),就会出现问题。
总而言之,不鼓励使用文件句柄作为FH,因为它们是全局变量,并且在更复杂的程序中产生“有趣”的问题。而是像这样使用open:
open my $fh, 'filename';
或更好:
open my $fh, '<', 'filename';
答案 3 :(得分:0)
首先,纠正:
while (<F2>) {
my $str = $_;
如果您希望读取的行在$str
中结束,则没有理由让$_
参与此过程:
while(my $ str =){
这也提出了depesz使用词汇文件句柄而不是打包全局裸字文件句柄的观点。
现在,看看你的循环:
my $count = 0;
while (my $str = <$input_fh>) {
$str =~ s/$arr[$count]/$count+1/g;
# ...
}
似乎有一个隐含的假设,即文件中的行数不能超过@foo
中的元素数。在这种情况下,您无需使用$count
:$.
也可以。假设你在第二行。您的代码表示您希望用BB
替换该行上2
的所有匹配项,这与您口头描述的内容不同。
这一点非常重要:您发布的任何代码都应与口头描述保持一致。
无论如何,这是一种方式:
<强> rty.pl 强>
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
my ($input) = @ARGV;
write_file(
$input, [
map { s/( ([A-Z]) \2 )/ord($2) - ord('A') + 1/gex; $_ } read_file $input
]
);
__END__
<强> test.data:强>
Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE
$ rty.pl test.data
脚本调用后test.data:
Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5
答案 4 :(得分:0)
无论哪种方式都可行
my%arr2 =('AA'=&gt; 1,'BB'=&gt; 2,'CC'=&gt; 3,'DD'=&gt; 4,'EE'=&gt; 5,'FF “=→6);
打开F2,“t1.txt”;
打开F3,“&gt; out.txt”;
而(){
我的$ str = $ ;
print F3 join'',map {s / $ / $ arr2 {$ } / g; $ } split / /,$ str;
打印F3“\ n”;
}
接近(F2);
关闭(F3);
或
我的@ arr1 =(“AA”,“BB”,“CC”,“DD”,“EE”,“FF”);
我的%hashArr = map {($ arr1 [$ ] =&gt; $ + 1)}(0 .. $#arr1);
打开F2,“t1.txt”;
打开F3,“&gt; out.txt”;
而(){
我的$ str = $ ;
print F3 join'',map {s / $ / $ hashArr {$ } / g; $ } split / /,$ str;
打印F3“\ n”;
}
接近(F2);
关闭(F3);