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

20150518<114319747011000001>,20150518230002,,917696706652,01,,52727,rch,,admin,,,,01,21314,,,,bulkpull2

My text file contains this type of lines. In first you can identify Date. I want to replace it with "18 May 2015" in the same file like

18 May 2015 <114319747011000001>,20150518230002,,917696706652,01,,52727,rch,,admin,,,,01,21314,,,,bulkpull2

I am coming by step to step. When i am here it gives an error.

open(DATA,"<Pull-2015-5-18-23.txt"); my $find = "20150518"; my $replace = "18 May 2015"; while(my $line = <DATA>) { $line =~ s/$find/$replace/g; print $line; }
Error: Can't modify constant item in scalar assignment at date.pl line 1, near "10," Execution of date.pl aborted due to compilation errors.

Replies are listed 'Best First'.
Re: using s///g;
by GrandFather (Saint) on Aug 06, 2015 at 11:36 UTC
    use strict; use warnings; my $find = "20150518"; my $replace = "18 May 2015"; while (my $line = <DATA>) { $line =~ s/$find/$replace/g; print $line; } __DATA__ 20150518

    Prints:

    18 May 2015

    as expected which leads me to think that the code you show is not the code you executed to get the error. Maybe you can modify the test code I've given to reproduce your error then show us that version?

    Premature optimization is the root of all job security
      Ya exactly its printing on the terminal correctly but the actual data not changing. But i want to change in the file also.
Re: using s///g;
by taiko (Sexton) on Aug 06, 2015 at 11:38 UTC
    Try this It will save the "old" file to file with *.old as an extension and new file with original name with your modifications
    local $^I = '.old'; local @ARGV = ( 'your_file_name' ); my $find = "20150518"; my $replace = "18 May 2015"; while ( <>){ s/$find/$replace/g; print; }
      Is it possible to change the data without changing extension, name & path of the file????
        Nope, you essentially can't change a free-format sequential file like that. That's why, behind the scene, you have to rename your original file (say into file.old), and then write your changed content to a new file having the name of your original file.

        The alternative is to read the whole file into memory, make the changes in memory and then clobber the content of the original file and write the new content to it.

        The modified file will have same extension and name as original file
        Original/unmodified file will get new extension *.old.
Re: using s///g;
by GotToBTru (Prior) on Aug 06, 2015 at 12:39 UTC

    You can open the file for both read and write, but that can be tricky. Better to create a new file and rename to old file name.

    use strict; use warnings; use File::Copy; my $infilename = 'Pull-2015-08-15-23.txt'; my $outfilename = 'new.file'; my $find = '20150518'; my $replace = '18 May 2015'; open $infile,'<',$infilename; open $outfile,'>',$outfilename; while (my $line = <$infile>) { $line =~ s/$find/$replace/; print $outfile $line; } close $infile; close $outfile; move($outfilename,$infilename);

    You may find modules like Date::Parse and Date::Format useful to deal with dates in general, and not just this specific example.

    Update:

    use Date::Parse; use Date::Format; @time = strptime("20150518"); print strftime("%e %b %Y",@time);
    Dum Spiro Spero
Re: using s///g;
by ww (Archbishop) on Aug 06, 2015 at 12:02 UTC
    # #1137654 my $find = "20150518<"; # assumes that a date-like value not +followed by a '<' is not what you seek my $replace = "18 May 2015"; while(my $line = <DATA>) { if($line =~ $find) { # select lines to print, unless you want + all lines * Note1 s/$find/$replace/g; # UPDATE: but the slash-g is utterly unne +cessary print $line; # as it would act only on single line +s in this case } } # * Note1: acknowledged: you want all lines. (another update) =head output 20150518<114319747011000001>, 20150518<bulkbull3>, =cut __DATA__ 20150518<114319747011000001>, 20150518230002,< >, 917696706652,01, , 52727, rch,, admin,, 01,21314,, bulkpull2,, 20150518<bulkbull3>,

    check Ln42!

Re: using s///g;
by SimonPratt (Friar) on Aug 06, 2015 at 11:52 UTC

    You can't open DATA directly like that, which is what the error message is telling you. Either change DATA to something else, or (preferably) switch to the three form method of opening files: open my $data, '<', 'Pull-2015-5-18-23.txt' or die 'failed to open file';

      Did you run the OP's code? Did you test your assumption? Obviously not because:

      use strict; use warnings; my $filename = 'data.txt'; open DATA, '>', $filename or die "Can't create $filename: $!\n"; print DATA <<STUFF; Stuff written to disk using file handle DATA STUFF close DATA; open my $inFile, '<', 'data.txt' or die "Can't open $filename: $!\n"; print <$inFile>; close $inFile;

      Prints:

      Stuff written to disk using file handle DATA

      which would fail with the OP's error message if you were right. In fact I can't see how you get your implied error of "Can't use DATA in a file open statement" from 'Can't modify constant item in scalar assignment at date.pl line 1, near "10,"'.

      Premature optimization is the root of all job security