如何在perl中更新文本文件的某些部分

时间:2015-03-13 09:46:35

标签: regex perl

我已经编写了代码,但它运行不正常。我希望将此“/”改为“\”。

use strict;
use warnings;

open(DATA,"+<unix_url.txt") or die("could not open file!");

while(<DATA>){

s/\//\\/g;
s/\\/c:/;
print DATA $_;

}

close(DATA);

我的原始文件是

/etc/passwd 
/home/bob/bookmarks.xml 
/home/bob/vimrc

预期产出

C:\etc\passwd
C:\home\bob\bookmarks.xml
C:\home\bob\vimrc 

原始输出

/etc/passwd
/home/bob/bookmarks.xml
/home/bob/vimrc/etc/passwd
\etc\passwd
kmarks.xml
kmarks.xml
mrcmrc

3 个答案:

答案 0 :(得分:1)

如果练习的重点不是使用正则表达式,而是关于完成任务的更多内容,我会考虑使用File::Spec系列中的模块:

use warnings;
use strict;
use File::Spec::Win32;
use File::Spec::Unix;
while (my $unixpath = <>) {
  my @pieces = File::Spec::Unix->splitpath($unixpath);
  my $winpath = File::Spec::Win32->catfile('c:', @pieces);
  print "$winpath\n";
}

答案 1 :(得分:1)

尝试在读取到同一文件末尾的while循环中逐行读取和写入相同的文件,看起来非常冒险且不可预测。我完全不确定每次尝试写入时文件指针的结束位置。您可以更安全地将输出发送到新文件(如果愿意,可以将其移动以替换旧文件)。

open(DATA,"<unix_url.txt") or die("could not open file for reading!");
open(NEWDATA, ">win_url.txt") or die ("could not open file for writing!");

while(<DATA>){
    s/\//\\/g;
    s/\\/c:\\/;
    #       ^ (note - from your expected output you also wanted to preserve this backslash)
    print NEWDATA $_;
}

close(DATA);
close(NEWDATA);
rename("win_url.txt", "unix_url.txt");

另见这个答案: Perl Read/Write File Handle - Unable to Overwrite

答案 2 :(得分:0)

你真的不需要写一个程序来做到这一点。你可以使用Perl Pie:

perl -pi -e 's|/|\\|g; s|\\|c:\\|;' unix_url.txt

但是,如果您在Windows上运行并使用Cygwin,我建议使用将POSIX路径转换为Windows路径的cygpath工具。

此外,您需要引用路径,因为它允许在Windows路径中包含空格。或者,您可以转义空格char:

perl -pi -e 's|/|\\/g; s|\\|c:\\|; s| |\\ |g;' unix_url.txt

现在关于你的初始问题,如果你仍想使用自己的脚本,你可以使用它(如果你想要备份):

use strict;
use autodie;
use File::Copy;

my $file = "unix_url.txt";
open my $fh,  "<",  $file;
open my $tmp, ">", "$file.bak";
while (<$fh>) {
    s/\//\\/g;
    s/\\/c:/;
} continue { print $tmp $_ }
close $tmp;
close $fh;
move "$file.bak", $file;