in reply to find and replace from shell

Edit- I found out that because the shell reads each file one line at a time, it would be impossible to do a find and replace with regex on this string
if ((!($session_login)) or ($session_access < 5)) { header("Window-Target: _top"); header("Location: index.php"); }

Is it true that I cannot do a regex find on a 'string' that spans multiple line breaks?
if so, does someone have a syntax example for how to make a little script that could do this find and replace?
Thanks!

Replies are listed 'Best First'.
Re^2: find and replace from shell
by graff (Chancellor) on Jun 17, 2010 at 07:32 UTC
    Here's a perl script that you could run with one or more file names as command line args, and each file would be edited:
    #!/usr/bin/perl use strict; for my $file ( @ARGV ) { { local $/; open( my $fh, "<", $file ) or do { warn "unable to read $file\ +n"; next }; $_ = <$fh>; } s/( \{ \s* header\("Window-Target:\s*_top"\); \s* header\("Location:\s*index\.php"\); ) \s* \} /$1\n exit;\n}/gx; { open( my $fh, ">", $file ) or do { warn "unable to edit $file\ +n"; next }; print $fh $_; } }
    Note the following:
    • using the "x" modifier (so the regex can be arranged more legibly)
    • using capturing parens in regex to simplify replacement
    • using "\s*" to match all the (potentially variable) white space (this is the only way you must use something like this to match white space when using the "x" modifier, but you should be handling white space this way in any case)
    • using lexically-scoped file handles in minimal blocks
    • using local $/ for slurp mode (in same scope as file handle)
    • skipping files that can't be read or written (and showing a warning each time)
    • if the script is run a second time on the same file, it'll just rewrite the file without changing it (because the regex won't match)
    And if I'm taking the trouble to store this edit operation as a little perl script all by itself (which I think is a Good Idea), I would also take the time to add some POD commentary to say why I wrote this script in the first place.
      Thanks Graff!
      can I get an example on the correct syntax for inputting the command line args?

      so in my shell, would that be something like...

      mypath/findreplace.pl _test.php

      also, are there substitutions to make in the script, such as $fh (my filehandle)?
      Thank you very much.
        You would normally run such a script as follows: let's say you saved the script as /home/yourname/bin/add-exits-to-php.pl and let's also assume that the directory  /home/yourname/bin is already mentioned in your shell's PATH variable.

        Given those assumptions, you can go to the directory where the php files are stored, and edit them all with these two command lines:

        cd /path/to/php_files/ add-exits-to-php.pl *.php
        In the (unlikely) event that there are so many php files (and their names are so long) that the shell can't fit them all on one command line (you see a report like "command line too long"), you could use the following approach instead:
        cd /path/to/php_files/ ls | grep '\.php$' | xargs add-exits-to-php.pl
        The "xargs" command is a standard *n*x utility that will accept an input list of any length, and will run a command as many times as necessary to make sure that the full list is processed using the given command.
      Hi Graff,
      I was able to get this to work. I am currently testing to see if can do the find replace on an entire directory.
      Thanks for your help Graff and JWKhaun so much. As a new perl programmer, I really appreciate this resource.