我在使用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";
答案 0 :(得分:26)
你在那里使用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
答案 1 :(得分:4)
尔。你正在使用printf。
printf将“%”解释为特殊的东西。
使用“print”代替。
如果必须使用printf,请使用
printf "%s", $content;
重要提示:
PrintF代表打印格式,就像在C中一样。
fprintf是C for File IO中的equivelant。
Perl不是C.
即使在IN C中,将您的内容作为参数1也可以出于安全原因而拍摄。
答案 2 :(得分:0)
甚至
perl -i bak -pe 's{status=["\'][\w ]*["\']\s*}{}gi;' yourfiles
-e说“有以下代码供您运行”
-i bak说“将旧文件重命名为whatever.bak”
-p在-e code
周围添加了一个读取打印循环Perl one-liners是一款功能强大的工具,可以为您节省大量的苦差事。
答案 3 :(得分:0)
如果您想要一个了解文档XML特性的解决方案(即,只删除状态属性,而不是匹配文本内容),您还可以使用XML::PYX:
$ pyx doc.xml | perl -ne'print unless /^Astatus/' | pyxw
答案 4 :(得分:0)
那是因为你使用了printf而不是print而且你知道printf不会打印“%”(因为它会认为你忘了键入格式符号,例如%s,%f等),除非你明确提到“% %”。 : - )