2

I'm migrating a directory of files containing fairly simple ASP code over to a PHP server and I need to modify the contents of all the files with a find and replace mechanism. I'm not great with regular expressions, but I've used this to change a few things already:

find . -name "*.php" -print0 | xargs -0 -n 1 sed -i -e 's/oldstring/newstring/g'

I have some complex strings I need to replace though. See the following:

FROM:

<% if request("page") = "" then %>

TO:

<?php if(!isset($_GET['page']) || !$_GET['page']){ ?>

This one, the * can be any number, then keep that number where the * is on the "TO".

FROM:

<% elseif request("page") = "*" then %>

TO:

<?php } elseif($_GET['page'] == '*'){ ?>

And the last one is pretty simple. FROM:

<% end if %>

TO:

<?php } ?>

If I can run this in bulk, recursively in a directory, this will fix 98% of all the ASP code in these files. I've tried to escape these strings in several ways, but cannot figure out how to get it to run. Any help is appreciated!

1 Answer 1

0

There are various ways of doing this, I would recommend taking advantage of Perl's quotemeta function.

First, make a tab separated text file containing the search patterns in the first column and their replacement in the second:

$ cat pats.txt                     
<% if request("page") = "" then %>  <?php if(!isset($_GET['page']) || !$_GET['page']){ ?>
<% elseif request("page") = "*" then %> <?php } elseif($_GET['page'] == '*'){ ?>
<% end if %>    <?php } ?>

I created a test file whose contents are:

$ cat foo.asp 
<% if request("page") = "" then %>
<% elseif request("page") = "*" then %>
<% end if %>

And Perl to the rescue:

find . -name "*.php" | while IFS= read -r file; do
  perl -i.bak -e 'open(A,"pats.txt");
             while(<A>){chomp; @a=split(/\t/); $k{quotemeta($a[0])}=$a[1]}
             while(<>){ 
              foreach $pat (keys(%k)){
                s/$pat/$k{$pat}/;
              } 
             print}' $file;
done

Perl's -i flag works just like in sed, you can specify an optional backup suffix. In the example above, a file called foo.php.bak will be created for each processed file. Use -i alone if you don't want the backups.

EXPLANATION:

The script will read the patterns and replacements and save the patterns as keys of a hash (%k) where the replacements are the values. The quotemeta function escapes all non ASCII (not matching [A-Za-z_0-9]) characters.

The script them opens the second file, looks for each pattern in each line and replaces accordingly. Since the search patterns has been escaped by quotemeta it is correctly recognized.

NOTES

This is obviously not the most efficient way of doing this since it will have to look for each of the patterns on each line. Still, it works and is much simpler than mucking about trying to manually escape everything.

The script will fail for files with new lines in the names. I assume that won't be a problem here.

2
  • Thanks so much this worked flawless. I also was unsure of a couple things so I wanted to post a comment. To use this, create a something.sh file and place the contents in there. Then run it by executing it: $ . something.sh - This is what I did, but it took me a while to figure this out. I'm very new to linux command line. Thanks for the help!
    – solepixel
    Commented Jun 10, 2013 at 3:01
  • @solepixel actually, you can just paste it directly into a terminal, it is a command line.
    – terdon
    Commented Jun 10, 2013 at 11:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .