我正在尝试解决以下问题。
我有2个文件。 Address.txt和File.txt。我想用perl脚本将所有A / B / C / D(File.txt)替换为相应的字符串值(从Address.txt文件读取)。它不会替换我的输出文件。我得到的文件内容与File.txt相同。 我试过下面的代码。
这是Address.txt文件
A,APPLE
B,BAL
C,CAT
D,DOG
E,ELEPHANT
F,FROG
G,GOD
H,HORCE
这是File.txt
A B C
X Y X
M N O
D E F
F G H
这是我的代码:
use strict;
use warnings;
open (MYFILE, 'Address.txt');
foreach (<MYFILE>){
chomp;
my @data_new = split/,/sm;
open INPUTFILE, "<", $ARGV[0] or die $!;
open OUT, '>ariout.txt' or die $!;
my $src = $data_new[0];
my $des = $data_new[1];
while (<INPUTFILE>) {
# print "In while :$src \t$des\n";
$_ =~ s/$src/$des/g;
print OUT $_;
}
close INPUTFILE;
close OUT;
# /usr/bin/perl -p -i -e "s/A/APPLE/g" ARGV[0];
}
close (MYFILE);
如果我写 $ _ = ~s / A / Apple / g;
然后输出文件正常,A正在替换为“Apple”。但是当它动态出现时它就不会被替换。
提前致谢。我是perl脚本语言的新手。如果我错了,请纠正我。
更新1:我更新了以下代码。现在工作正常。我的问题是这个算法的大O. 代码:
#!/usr/bin/perl
use warnings;
use strict;
open( my $out_fh, ">", "output.txt" ) || die "Can't open the output file for writing: $!";
open( my $address_fh, "<", "Address.txt" ) || die "Can't open the address file: $!";
my %lookup = map { chomp; split( /,/, $_, 2 ) } <$address_fh>;
open( my $file_fh, "<", "File1.txt" ) || die "Can't open the file.txt file: $!";
while (<$file_fh>) {
my @line = split;
for my $char ( @line ) {
( exists $lookup{$char} ) ? print $out_fh " $lookup{$char} " : print $out_fh " $char ";
}
print $out_fh "\n";
}
答案 0 :(得分:4)
不完全确定您希望如何格式化输出。你想保持行和列的原样吗?
我采用了与上述类似的方法,但保持格式与'file.txt'文件中的格式相同:
#!/usr/bin/perl
use warnings;
use strict;
open( my $out_fh, ">", "output.txt" ) || die "Can't open the output file for writing: $!";
open( my $address_fh, "<", "address.txt" ) || die "Can't open the address file: $!";
my %lookup = map { chomp; split( /,/, $_, 2 ) } <$address_fh>;
open( my $file_fh, "<", "file.txt" ) || die "Can't open the file.txt file: $!";
while (<$file_fh>) {
my @line = split;
for my $char ( @line ) {
( exists $lookup{$char} ) ? print $out_fh " $lookup{$char} " : print $out_fh " $char ";
}
print $out_fh "\n";
}
这会给你输出:
APPLE BAL CAT
X Y X
M N O
DOG ELEPHANT FROG
FROG GOD HORCE
答案 1 :(得分:2)
这是让Perl处理文件打开和关闭的另一个选项:
use strict;
use warnings;
my $addresses_txt = pop;
my %hash = map { $1 => $2 if /(.+?),(.+)/ } <>;
push @ARGV, $addresses_txt;
while (<>) {
my @array;
push @array, $hash{$_} // $_ for split;
print "@array\n";
}
用法:perl File.txt Addresses.txt [>outFile.txt]
最后一个可选参数将输出定向到文件。
数据集输出:
APPLE BAL CAT
X Y X
M N O
DOG ELEPHANT FROG
FROG GOD HORCE
地址'文件的名称隐含pop
来自@ARGV供以后使用。然后,使用File.txt中的键/值对构建哈希。
读取地址文件,split
将每一行放入其单个元素中,并使用defined-or(//
)运算符返回定义的散列项或单个元素,然后push
编辑到@array。最后,数组以print
语句进行插值。
希望这有帮助!
答案 2 :(得分:1)
首先,这是您现有的程序,稍微重写
打开地址文件
将地址文件转换为哈希值,以便字母为键,字符串为值
打开其他文件
读入其中的单行
将该行拆分为单个字母
使用字母在哈希
中查找use strict;
use warnings;
open(my $a,"Address.txt")||die $!;
my %address=map {split(/,/) } map {split(' ')} <$a>;
open(my $f,"File.txt")||die $!;
my $list=<$f>;
for my $letter (split(' ',$list)) {
print $address{$letter}."\n" if (exists $address{$letter});
}
使另一个具有替换的文件改变处理$list
for my $letter (split(' ',$list)) {
if (exists $address{$letter}) {
push @output, $address{$letter};
}
else {
push @output, $letter;
}
}
open(my $o,">newFile.txt")||die $!;
print $o "@output";
答案 3 :(得分:1)
您的问题是,在foreach循环的每次迭代中,您都会覆盖之前对输出文件所做的任何更改。
我的解决方案:
use strict;
use warnings;
open my $replacements, 'Address.txt' or die $!;
my %r;
foreach (<$replacements>) {
chomp;
my ($k, $v) = split/,/sm;
$r{$k} = $v;
}
my $re = '(' . join('|', keys %r) . ')';
open my $input, "<", $ARGV[0] or die $!;
while (<$input>) {
s/$re/$r{$1}/g;
print;
}
答案 4 :(得分:0)
#!/usr/bin/perl -w
# to replace multiple text strings in a file with text from another file
#select text from 1st file, replace in 2nd file
$file1 = 'Address.txt'; $file2 = 'File.txt';
# save the strings by which to replace
%replacement = ();
open IN,"$file1" or die "cant open $file1\n";
while(<IN>)
{chomp $_;
@a = split ',',$_;
$replacement{$a[0]} = $a[1];}
close IN;
open OUT,">replaced_file";
open REPL,"$file2" or die "cant open $file2\n";
while(<REPL>)
{chomp $_;
@a = split ' ',$_; @replaced_data = ();
# replace strings wherever possible
foreach $i(@a)
{if(exists $replacement{$i}) {push @replaced_data,$replacement{$i};}
else {push @replaced_data,$i;}
}
print OUT trim(join " ",@replaced_data),"\n";
}
close REPL; close OUT;
########################################
sub trim
{
my $str = $_[0];
$str=~s/^\s*(.*)/$1/;
$str=~s/\s*$//;
return $str;
}