Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I would like to know how I can create a file that contain special characters in Perl. I have been trying to create a file, with the following function, and it works but it creates an error when it run. I think it is due to the data I am trying to put in my file, for example there are %, @ and others that are to be printed in the file, and I think that the error is due to this. Any ideas on how I can accomplish this? I have attached my code with the error message and one line to be put in the file. Thanks,
sub CreateConfig{ my ($file,@data) = @_; $file = $file.".new"; open(NFILE,">$file"); foreach my $item (@data){ printf NFILE "$item\n"; } close(NFILE); }
Error: Modification of a read-only value attempted
One line of data from the array @data: passwd chat = *New*UNIX*password* %n\n *ReType*new*UNIX*password* %n\n *passwd:*all*authentication*tokens*updated*successfully*

Replies are listed 'Best First'.
Re: Escaping special chars to add in a file
by Corion (Patriarch) on Apr 03, 2008 at 08:59 UTC

    The easy fix is to use print instead of printf. See also the documentation of printf, which says:

    Don't fall into the trap of using a printf when a simple print would do. The print is more efficient and less error prone.

    I'm not sure why printf has this problem, but it seems to fatally dislike that you pass it strings with arguments to be interpolated (%) where there is nothing to interpolate. I'm not sure that it should choke on this. I won't provide you the "other easy" fix for this, because you should use print instead if you want to output a simple string.

    You should also indent your code properly, not clobber NFILE (or even better, use lexical filehandles) and check whether open fails:

    use strict; sub CreateConfig{ my ($file,@data) = @_; $file = $file.".new"; local *NFILE; open(NFILE,">$file") or die "Couldn't create '$file': $!"; foreach my $item (@data){ print NFILE "$item\n"; }; close(NFILE); } CreateConfig('test.cfg','passwd chat = *New*UNIX*password* %n\n *ReTyp +e*new*UNIX*password* %n\n *passwd:*all*authentication*tokens*updated* +successfully*');

      I'm not sure why printf has this problem...

      It's specifically the %n format that does this. According to sprintf, this "*stores* the number of characters output so far into the next variable in the parameter list". If there is no next variable, this is the error you get. This came up about a year ago in line number ($.) problem ?.

      I think the error message could use improvement, but it seems fairly logical that it is an error.

Re: Escaping special chars to add in a file
by ikegami (Patriarch) on Apr 03, 2008 at 08:54 UTC

    printf NFILE "$item\n";
    should be
    printf NFILE "%s\n", $item;
    or
    print NFILE "$item\n";

    The "f" in "printf" stands for "format" (not "file"), and you didn't provide one.

    Ref: print, printf