Why does my Perl script remove characters from a file?

I have a problem with a Perl script. It changes the contents of the file, then opens it again to write it, and in the process some characters are lost. All words starting with '%' are deleted from the file. This is pretty annoying because% expressions are variable placeholders for dialogs.

Do you have any idea why? The source file is default encoded XML

Here is the code:

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"; 
+1
source share
5 answers

You use printf there, and it considers its first argument to be a format string. See printf documentation for more details. When I encounter such a problem, I always guarantee that I use the functions correctly. :)

You probably want just print :

  print FILE $content; 

In your example, you do not need to read the entire file, since your substitution does not cross the lines. Instead of trying to read and write the same file name at the same time, use a temporary file:

 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"; 

It also comes down to this command line program:

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

Er. You are using printf.

printf interprets "%" as something special.

use "print" instead.

If you need to use printf, use

 printf "%s", $content; 

Important Note:

PrintF stands for print format, as in C.

fprintf is equivariant in C for the IO file.

Perl is not C.

And even in IN C, so that your content as parameter 1 gets in your eyes for security reasons.

+4
source

Or even

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

-e says "there is the code to run next"

-i bak says: "Rename the old file to what.bak"

-p adds a read-print loop around -e code

Perl one-liners is a powerful tool and can save you a lot of effort.

0
source

If you need a solution that is familiar with the XML nature of documents (that is, only remove status attributes and do not match the contents of the text), you can also use XML :: PYX :

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

This is because you used printf instead of printing, and you know that printf does not print "%" (because you think you forgot to enter a format character, such as% s,% f, etc.), unless you explicitly specify "%%". :-)

0
source

All Articles