1

我正在尝试解决以下问题。

我有 2 个文件。地址.txt 和文件.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

这是文件.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:我更新了下面的代码。现在工作正常。我的问题是这个算法的大问题。代码 :

#!/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";
}
4

5 回答 5

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 
于 2013-10-19T10:25:45.793 回答
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每一行放入其单个元素中,然后使用定义或 ( //) 运算符返回定义的哈希项或单个元素,然后将其push编辑到 @array 上。最后,数组被插入到一个print语句中。

希望这可以帮助!

于 2013-10-19T19:45:58.070 回答
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";
于 2013-10-19T08:14:47.277 回答
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;
}
于 2013-10-19T10:32:57.813 回答
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;
}
于 2013-10-21T18:16:56.147 回答