String 需要打开一个文件并替换多个字符串

String 需要打开一个文件并替换多个字符串,string,file,perl,replace,String,File,Perl,Replace,我有一个很大的xml文件。它里面有一些递增的数字,我想用一个不同的递增数字来代替。我已经看过了,这是以前有人建议的。不幸的是,我无法让它工作:( 在下面的代码中,40960的所有实例都应该替换为41984,40961的所有实例都应该替换为41985等等。什么都没有发生。我做错了什么 use strict; use warnings; my $old = 40960; my $new = 41984; my $string; my $file = 'file.txt'; rename($fi

我有一个很大的xml文件。它里面有一些递增的数字,我想用一个不同的递增数字来代替。我已经看过了,这是以前有人建议的。不幸的是,我无法让它工作:(

在下面的代码中,40960的所有实例都应该替换为41984,40961的所有实例都应该替换为41985等等。什么都没有发生。我做错了什么

use strict;
use warnings;

my $old = 40960;
my $new = 41984;
my $string;

my $file = 'file.txt';

rename($file, $file.'.bak');
open(IN, '<'.$file.'.bak') or die $!;
open(OUT, '>'.$file) or die $!;

$old++;
$new++;

for (my $i = 0; $i < 42; $i++) {
    while(<IN>) {
        $_ =~ s/$old/$new/g;
        print OUT $_;
    }
}

close(IN);
close(OUT);
使用严格;
使用警告;
我的$old=40960;
my$new=41984;
我的$string;
my$file='file.txt';
重命名($file,$file.'.bak');
打开(在、.$文件中)或死亡$!;
$old++;
$new++;
对于(我的$i=0;$i<42;$i++){
while(){
$\=~s/$old/$new/g;
打印出美元;
}
}
关闭(IN);
收尾;

这里有一种替代方法,可以将输入文件读入字符串,并同时进行所有替换:

use strict;
use warnings;

{
my $old = 40960;
my $new = 41984;

my ($regexp) = map { qr/$_/ } join '|', map { $old + $_ } 0..41;

my $file = 'file.txt';
rename($file, $file.'.bak');
open(IN, '<'.$file.'.bak') or die $!;
my $str = do {local $/; <IN>};
close IN;
$str =~ s/($regexp)/do_subst($1, $old, $new)/ge;

open(OUT, '>'.$file) or die $!;
print OUT $str;
close OUT;

}

sub do_subst {
    my ( $old, $old_base, $new_base ) = @_;
    my $i = $old - $old_base;
    my $new = $new_base + $i;
    return $new;
}
使用严格;
使用警告;
{
我的$old=40960;
my$new=41984;
my($regexp)=map{qr/$\/}join'|',map{$old+$\}0..41;
my$file='file.txt';
重命名($file,$file.'.bak');
打开(在、.$文件中)或死亡$!;
打印$str;
收尾;
}
sub do_subst{
我的($old,$old_base,$new_base)=@;
我的$i=$old-$old_基数;
my$new=$new_base+i;
退回$new;
}

注意:使用

可能会提高效率。这里有一种替代方法,可以将输入文件读入字符串,并同时执行所有替换:

use strict;
use warnings;

{
my $old = 40960;
my $new = 41984;

my ($regexp) = map { qr/$_/ } join '|', map { $old + $_ } 0..41;

my $file = 'file.txt';
rename($file, $file.'.bak');
open(IN, '<'.$file.'.bak') or die $!;
my $str = do {local $/; <IN>};
close IN;
$str =~ s/($regexp)/do_subst($1, $old, $new)/ge;

open(OUT, '>'.$file) or die $!;
print OUT $str;
close OUT;

}

sub do_subst {
    my ( $old, $old_base, $new_base ) = @_;
    my $i = $old - $old_base;
    my $new = $new_base + $i;
    return $new;
}
使用严格;
使用警告;
{
我的$old=40960;
my$new=41984;
my($regexp)=map{qr/$\/}join'|',map{$old+$\}0..41;
my$file='file.txt';
重命名($file,$file.'.bak');
打开(在、.$文件中)或死亡$!;
打印$str;
收尾;
}
sub do_subst{
我的($old,$old_base,$new_base)=@;
我的$i=$old-$old_基数;
my$new=$new_base+i;
退回$new;
}

注意:使用

可能会提高效率这里有一个逐行运行的示例,因此文件大小无关紧要。该示例假设您要替换“45678”,而不是“fred45678”。该示例还假设存在一个数字范围,并且您希望将其替换为一个新的范围偏移量(以常量表示)

#!/usr/bin/perl

use strict;
use warnings;

use constant MIN => 40000;
use constant MAX => 90000;
use constant DIFF => +1024;

sub repl { $_[0] >= MIN && $_[0] <= MAX ? $_[0] + DIFF : $_[0] }

while (<>) {
    s/\b(\d+)\b/repl($1)/eg;
    print;
}
exit(0);
…它产生这个输出

foo bar 123
41024 51024 61024 99999
fred60000
fred 61024 fred

这里有几个经典的Perlism,但是如果您适当地RTFM,那么这个示例应该不难理解。

这里有一个逐行运行的示例,因此文件的大小无关紧要。该示例假设您要替换“45678”之类的内容,而不是“fred45678”。该示例还假设存在一个数字范围,并且您希望将其替换为一个新的范围偏移量(以常量表示)

#!/usr/bin/perl

use strict;
use warnings;

use constant MIN => 40000;
use constant MAX => 90000;
use constant DIFF => +1024;

sub repl { $_[0] >= MIN && $_[0] <= MAX ? $_[0] + DIFF : $_[0] }

while (<>) {
    s/\b(\d+)\b/repl($1)/eg;
    print;
}
exit(0);
…它产生这个输出

foo bar 123
41024 51024 61024 99999
fred60000
fred 61024 fred

这里有几个经典的Perlism,但是如果您适当地RTFM,那么这个示例应该不难理解。

其他答案可以为您的问题提供更好的解决方案。我的重点是解释代码不起作用的原因

代码的核心是:

$old++;
$new++;

for (my $i = 0; $i < 42; $i++) {
    while(<IN>) {
        $_ =~ s/$old/$new/g;
        print OUT $_;
    }
}

其他答案为您的问题提供了更好的解决方案。我的答案集中于解释为什么您的代码不起作用

代码的核心是:

$old++;
$new++;

for (my $i = 0; $i < 42; $i++) {
    while(<IN>) {
        $_ =~ s/$old/$new/g;
        print OUT $_;
    }
}

对于
for
循环中的每个迭代,您可能必须回溯到输入文件的开头,请参阅。但是,可能有更有效的方法可以让您一次替换所有数字。对于
for
循环中的每个迭代,您可能必须回溯到输入文件的开头,请参阅。但是可能有更有效的方法让你一次替换所有数字的nt方法谢谢,我意识到我的循环放置失败了,但完全忽略了文件句柄问题。谢谢,我意识到我的循环放置失败了,但完全忽略了文件句柄问题。我的xml文件很大,我想如果c转换为字符串。我的xml文件相当大,我想知道如果转换为字符串是否会引起问题。这看起来很有趣,但对于像我这样的初学者来说也很复杂。你能添加一些注释吗?repl()是一个简单的函数,给定x,如果x>=MIN和x,它返回x+DIFF,这看起来很有趣,但对于像我这样的初学者来说也很复杂。你能添加一些关于什么的注释吗?repl()是一个简单的函数,给定x,如果x>=MIN和x,它返回x+DIFF