in reply to Re^8: search and replace strings in different files in a directory (Path::Tiny)
in thread search and replace strings in different files in a directory

Dear Athanasius,

Thank you for going through my comments and providing feedback. I am quite happy that I was not completely wrong about all lines.

However some questions remain:

Why was the subroutine called with 6 passed as an argument. Was this just for demonstrating that not only strings but also numbers can be passed to a sub?.

Could you please clarify why only the first argument $ra is passed an the others remain in the array? Does that mean that arguments to a sub are passed in some kind of for loop?

my( $ra ) = @_; # variable for the argument(s) passed to the sub, @_ accepts every + argument passed to sub, i.e. the files passed to main

Looking forward to your feedback. Will work on the inital code and try to use more subroutines.

Thanks a mil for your support

Kind regards

C.
  • Comment on Re^9: search and replace strings in different files in a directory (Path::Tiny)
  • Download Code

Replies are listed 'Best First'.
Re^10: search and replace strings in different files in a directory (Path::Tiny)
by Athanasius (Archbishop) on Aug 28, 2014 at 14:59 UTC

    Hello PitifulProgrammer,

    Why was the subroutine called with 6 passed as an argument. Was this just for demonstrating that not only strings but also numbers can be passed to a sub?

    Maybe, I don’t know, I didn’t write the code. ;-)

    Could you please clarify why only the first argument $ra is passed an the others remain in the array? Does that mean that arguments to a sub are passed in some kind of for loop?

    No, no, no! Perl is not like C, where arguments are passed by value (i.e., as local copies). In Perl, arguments are passed by reference. Specifically, the arguments passed into a subroutine are available within that subroutine in the special array variable @_ (also called @ARG), which contains aliases to the originals.

    What this means is that if you call foo($bar, $baz), then within that call to sub foo the variable $_[0], which is the first element of the array @_, is an alias for $bar, and likewise $_[1] is an alias for $baz. So if you change $_[0] within the subroutine, when you return from the subroutine you find that $bar has changed too.

    Sometimes this is what you want, but mostly it isn’t. So the usual practice is to make local copies of the arguments before using them. These local copies are not aliases, so changing the local copies has no effect on the originals. There are two ways of creating the local copies:

    1. Within a sub, when shift is used without an explicit argument it automatically shifts @_. For example,

      sub foo { my $x = shift; my $y = shift; ...

      This removes the first two elements from @_ and makes copies of them in $x and $y, respectively.

    2. Simple assignment:

      sub foo { my ($x, $y) = @_; ...

      This makes local copies of the first two elements of @_, but @_ itself remains unchanged.

    Please see the entry for @_ in perlvar, and study perlsub, especially the third paragraph of the “DESCRIPTION” section.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re^10: search and replace strings in different files in a directory
by Anonymous Monk on Aug 28, 2014 at 23:22 UTC

    I'd like to thank Athanasius for picking up the slack :)

    Why was the subroutine called with 6 passed as an argument. Was this just for demonstrating that not only strings but also numbers can be passed to a sub?.

    :) To demonstrates that arguments can be passed and they end up in @_ ... so you can lookup @_ in perlvar and read about it :)

    Its also so you can resolve the issue you had in Re^2: search and replace strings in different files in a directory (Path::Tiny), something like

    Or (less complete but the sub names is the idea of this idea )

    or more fun with names

    The idea is to have many many many subroutines, and give them names that are memorable... I chose Diddle because RenameMe didn't fit for this problem, and I'm kinda tired of NotDemoMeaningfulName and NotMainMeaningfulNameYouPick is tad long :)

     

    Athanasius is doing pretty well :)(thanks) and I'd like to add a little note on why Main/exit, its for ease of writing/debugging/maintaining/documenting the program. The program begins with Main( @ARGV ); and ends after Main completes .

    In other languages like C main() is mandatory, but its not mandatory in perl, so perl will let you write interwoven stuff like

    and this is very hard to read and maintain, but folks still do it and often struggle debugging this stuff; Main/exit combination is much easier on the brain :)

    You can read more about this Main/exit style convention /program template at (tye)Re: Stupid question (and see one discussion of that template at Re^2: RFC: Creating unicursal stars

    If you've got more questions, I'll be back :)

      Dear Monnks,

      I am getting the strange feeling that my undertaking of writing a "simple" script turns out to be a much larger project than I had anticipated.

      It is a bit frustrating, but we would not be humans if we could not learn from mistakes. Anyway, you kindly offered your help in your last reply and I think I need it (again), since I cannot figure out the current error messages I have been getting

      First message is Cygwin-related (not sure if this is the right place, should I open a new post?).

      What I can figure out is that Cygwin won't install the module, but I have not idea why, since any other installation of perl modules on this machine worked like a charm.

      NE Configuring S/SM/SMUELLER/PathTools-3.47.tar.gz with Makefile.PL Checking if your kit is complete... Looks good Generating a Unix-style Makefile Writing Makefile for Cwd Writing MYMETA.yml and MYMETA.json SMUELLER/PathTools-3.47.tar.gz /usr/bin/perl Makefile.PL -- OK Running make for S/SM/SMUELLER/PathTools-3.47.tar.gz cp lib/File/Spec/OS2.pm blib/lib/File/Spec/OS2.pm cp lib/File/Spec/Mac.pm blib/lib/File/Spec/Mac.pm cp lib/File/Spec/VMS.pm blib/lib/File/Spec/VMS.pm cp lib/File/Spec/Functions.pm blib/lib/File/Spec/Functions.pm cp lib/File/Spec/Epoc.pm blib/lib/File/Spec/Epoc.pm cp lib/File/Spec/Cygwin.pm blib/lib/File/Spec/Cygwin.pm cp lib/File/Spec.pm blib/lib/File/Spec.pm cp Cwd.pm blib/lib/Cwd.pm cp lib/File/Spec/Unix.pm blib/lib/File/Spec/Unix.pm cp lib/File/Spec/Win32.pm blib/lib/File/Spec/Win32.pm Running Mkbootstrap for Cwd () chmod 644 Cwd.bs /usr/bin/perl.exe /usr/lib/perl5/5.14/ExtUtils/xsubpp -typemap /usr/l +ib/perl5/5.14/ExtUtils/typemap Cwd.xs > Cwd.xsc && mv Cwd.xsc Cwd.c gcc-4 -c -DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g -fno-strict-ali +asing -pipe -fstack-protector -DUSEIMPORTLIB -O3 -DVERSION=\"3.47\" + -DXS_VERSION=\"3.47\" "-I/usr/lib/perl5/5.14/i686-cygwin-threads-64 +int/CORE" -DDOUBLE_SLASHES_SPECIAL=0 Cwd.c /bin/sh: gcc-4: Kommando nicht gefunden. Makefile:367: recipe for target 'Cwd.o' failed make: *** [Cwd.o] Error 127 SMUELLER/PathTools-3.47.tar.gz make -- NOT OK Failed during this command: SMUELLER/PathTools-3.47.tar.gz : make NO cpan[2]>

      I switched to my DOS cmd and thought this would work out, however, when running the script, I got this error message

      c:\dev>perl script.pl Wide character in die at C:/strawberry/perl/site/lib/Path/Tiny.pm line + 1492. Error opendir on '´&#9559;&#9488;Z:/../file.xml': Invalid argument at +script.pl line 57.

      line 57 in the script would be the line with ->children qr/.../(*.xml), which retrieves the xml files:

      sub RetrieveAndBackupXML { #~ my( $directory ) = @_; ## same as shift @_ ## same as shift my $directory = shift; my $date = POSIX::strftime( '%Y-%m-%d', localtime ); #sets cu +rrent date and time to be added to backup file my $bak = "$date.bak"; #date added to the .bak file my @xml_files = path( $directory )->children( qr/\.xml$/ ); for my $file ( @xml_files ) { Replace( $file, "$file-$bak" ); #sub Replace using it's 2 para +meters as defined below } }

      Those xml-files are unicode, so I am wondering why I am getting this wide character message again

      Would be grand if you guys could assist me in this matter, if you need more information about the code or my system let me know.

      Kind regards

      C.
        /bin/sh: gcc-4: Kommando nicht gefunden.

        This means you should install the gcc cygwin package. But unless you really, really need a recent version of File::Spec, don't upgrade File::Spec. It comes with the Perl core distribution and there rarely is a need to upgrade it. I haven't read the previous replies you already got, so there might be a reason to actually upgrade the module, but unless there is a pressing need to do so, I wouldn't.

        &#9559;&#9488;Z:/../file.xml

        Seems like BOM.

        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        I am getting the strange feeling that my undertaking of writing a "simple" script turns out to be a much larger project than I had anticipated.

        Its not that much larger, its just that there is a lot of details :) Its like learning to sing in a new language, there is new sentence structure and new word list ... and you still have to practice hitting your notes :)(reading about it is different than doing it)

        /bin/sh: gcc-4: Kommando nicht gefunden. Makefile:367: recipe for target 'Cwd.o' failed make: *** Cwd.o Error 127

        Like Corion already said, looks like you're missing gcc-4 :)

        Wide character in die at ... Path/Tiny. ... line 57 in the script

        Isn't that wonderfully convenient? I think so (problem detected, error reported informatively)

        So there is a problem with the filename, its got extra stuff. So, to solve the cause you work your way backwards, which function feeds RetrieveAndBackupXML? Which function feeds that function? Is it still called GetPaths? That is where you employ File::BOM, like

        sub GetPaths { use File::BOM; ## my @paths = path( shift )->lines_utf8; my @paths = path( shift )->lines( { binmode => ":via(File::BOM)" } + ); s/\s+$// for @paths; # "chomp" return @paths; } ## end sub GetPaths

        other way without File::BOM

        sub GetPaths { my @paths = path( shift )->lines_utf8; s/\x{feff}//g for @paths; # "de-bom" s/\s+$// for @paths; # "chomp" return @paths; } ## end sub GetPaths

        A tip: if you add use Carp::Always; you will get a stack of error messages, like

        makes it more obvious what sub feeds the dying one