如何使用perl脚本动态替换字符串

时间:2013-10-19 08:00:14

标签: perl replace

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

我有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";
}

5 个答案:

答案 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;
}