【问题标题】:I want to open a file and replace last occurrence pattern of string in perl我想打开一个文件并替换 perl 中字符串的最后出现模式
【发布时间】:2012-12-11 02:44:42
【问题描述】:

到目前为止,我已经这样做了,但仍然无法正常工作。

open (GOOD_FILE,"<$pre.XXX.XXX$post") or die "Cannot open XXX";

# temporarily undefine the input line separator to read the entire file at once:
my $text = do { local $/; <GOOD_FILE> };
close GOOD_FILE or die $!;
#File name to replace XXXX.XXXXX.XXXX.XXXX.CCCC where last CCCC can be     anything 
$text =~ s/^(.*\n)?XXXX\.XXXX\.XXXX\.[^\n]*/$1myname/s;

open (GOOD_FILE,"<$pre.XXXX.XXXX$post") or die "Cannot open XXXX";
print GOOD_FILE $text;
close GOOD_FILE or die $!;

输入文件如下所示:

I am tester testing
I am still learning.
XXXX.XXXX.XXXX.XXXX.CCCC
I am tester.
XXXX.XXXX.XXXX.XXXX.PPPP

它应该产生这个输出:

I am tester testing
I am still learning.
XXXX.XXXX.XXXX.XXXX.CCCC
I am tester.
myname.

但我得到的是空文件。

谢谢你们,我能够使用变量来解决问题,我只是将正则表达式作为变量,它工作正常。

【问题讨论】:

    标签: string perl replace pattern-matching last-occurrence


    【解决方案1】:

    当您open a file 使用&gt; 模式写入时,它会自动截断为零长度。

    可以使用+&lt; 模式同时打开一个文件进行读写,而不截断它,但实际上修改这样的文件有点棘手,因为它需要@ 987654322@.

    相反,有两种简单的方法可以实现您想要的。如果您知道文件总是相对较短,您可以将其读入内存,修改并写回:

    my $filename = 'filename.txt';
    
    open my $in, '<', $filename or die $!;
    # temporarily undefine the input line separator to read the entire file at once:
    my $text = do { local $/; <$in> };
    close $in or die $!;
    
    $text =~ s/^(.*\n)?MY\.FILE\.NAME\.[^\n]*/$1myname/s;
    
    open my $out, '>', $filename or die $!;
    print $out $text;
    close $out or die $!;
    

    对于大文件,另一种解决方案是将输出写入临时文件,然后在完成后将临时文件移到原始文件上。这或多或少是perl's -i switch 所做的,它允许您逐行编辑任意长的文件(只要您有足够的磁盘空间来存储副本)。不幸的是,在您的情况下,使用此方法匹配文件中特定字符串的 last 出现会有点棘手。

    (我想你可以使用File::ReadBackwards,但不幸的是没有 File::WriteBackwards 模块来配合它(而且很难写一个由于 OS 文件 I/O 接口的限制),因此您基本上必须将输出行以相反的顺序写入临时文件,然后再执行第二遍以将它们以正确的顺序复制回原始文件. 这应该是可能的,但有点复杂。)

    【讨论】:

    • 请查看更新后的代码,如果您能帮助我,那就太好了。
    • 写入时需要以&gt;模式打开文件,而不是&lt;。此外,看起来您的正则表达式在CAM 之后有一个额外的\.,即使在您的示例输入中该位置没有出现句点。最后,我强烈建议您使用use strict;use warnings; 开始您的脚本,并修复它们产生的任何投诉;我很确定启用警告会告诉你第一个错误。
    • 我已经使用了 use strick 和 use warnings 并更正了写入模式来写入文件,但仍然没有写入。这是我的替换 $text =~ s/^(.*\n)?NSHT\.FIN\.CAM0000\.ESCR\.INPUT01\.*/$1myname/s;
    • 要替换的文件是 NSH[T][P].FIN.CAM0000.ESCR.INPUT01.121210,其中日期可以是最后一个点之后的任何内容。文件名后面可能还有其他字符串,但那将在相同的空格之后,所以我删除了 \n 你最初的建议者。感谢您的帮助。
    • 好的,尝试将输出写入与您用于输入的文件不同的文件。如果新文件被写入但看起来与原始文件相同,则问题出在您的正则表达式中。如果没有写入,则问题出在您的文件 I/O 中。
    猜你喜欢
    • 1970-01-01
    • 2011-09-25
    • 2015-03-28
    • 2011-04-19
    • 2019-10-01
    • 2011-07-26
    • 1970-01-01
    • 2014-06-13
    相关资源
    最近更新 更多