【问题标题】:Why does my Perl script remove characters from the file?为什么我的 Perl 脚本会从文件中删除字符?
【发布时间】:2020-08-26 23:11:17
【问题描述】:

我对 Perl 脚本有一些疑问。它修改文件的内容,然后重新打开它来写入,在此过程中会丢失一些字符。从文件中删除所有以“%”开头的单词。这很烦人,因为 % 表达式是对话框的变量占位符。

你知道为什么吗?源文件是默认编码的 XML

代码如下:

undef $/;
open F, $file or die "cannot open file $file\n";
my $content = <F>;                                           
close F;                                                     
                                                               
$content =~s{status=["'][\w ]*["']\s*}{}gi;
                 
printf $content;

open F, ">$file" or die "cannot reopen $file\n";             
printf F $content;                                           
close F or die "cannot close file $file\n";

【问题讨论】:

    标签: perl file


    【解决方案1】:

    你在那里使用printf,它认为它的第一个参数是一个格式字符串。有关详细信息,请参阅printf documentation。当我遇到这类问题时,我总是确保我正确使用了这些功能。 :)

    你可能只想要print:

     print FILE $content;
    

    在您的示例中,您不需要读取整个文件,因为您的替换不会跨行。不要尝试一次读取和写入相同的文件名,而是使用临时文件:

    open my($in),  "<", $file       or die "cannot open file $file\n";
    open my($out), ">", "$file.bak" or die "cannot open file $file.bak\n";
    
    while( <$in> )
        {
        s{status=["'][\w ]*["']\s*}{}gi;
        print $out;
        }
    
    rename "$file.bak", $file or die "Could not rename file\n";
    

    这也简化为这个命令行程序:

    % perl -pi.bak -e 's{status=["\']\\w ]*["\']\\s*}{}g' file
    

    【讨论】:

      【解决方案2】:

      呃。您正在使用 printf。

      printf 将“%”解释为特殊的东西。

      改用“打印”。

      如果必须使用 printf,请使用

      printf "%s", $content;
      

      重要提示:

      PrintF 代表打印格式,就像在 C 中一样。

      fprintf 是 C 中文件 IO 的等价物。

      Perl 不是 C。

      甚至在 C 中,出于安全原因,将您的内容作为参数 1 也会让您被枪杀。

      【讨论】:

        【解决方案3】:

        甚至

        perl -i bak -pe 's{status=["\'][\w ]*["\']\s*}{}gi;' yourfiles
        

        -e 表示“下面有代码供你运行”

        -i bak 说“将旧文件重命名为whatever.bak”

        -p 在 -e 代码周围添加一个读取-打印循环

        Perl 单行代码是一种强大的工具,可以为您省去很多苦差事。

        【讨论】:

        • 不,-i bak 表示“将旧文件重命名为whateverbak”。不管.bak 是 -i .bak
        【解决方案4】:

        如果您想要一个了解文档 XML 特性的解决方案(即,仅删除状态属性,而不是匹配文本内容),您也可以使用 XML::PYX

        $ pyx doc.xml | perl -ne'print unless /^Astatus/' | pyxw
        

        【讨论】:

          【解决方案5】:

          那是因为您使用 printf 而不是 print,并且您知道 printf 不会打印“%”(因为它会认为您忘记输入格式符号,例如 %s、%f 等),除非您通过“%”明确提及%”。 :-)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-05-17
            • 2013-01-06
            • 2018-08-02
            • 2021-06-01
            • 2012-08-05
            • 1970-01-01
            • 2014-09-01
            • 1970-01-01
            相关资源
            最近更新 更多