3

I have 150+ PHP files I need to change (updating ereg to preg_match). I tired to update them manually but it takes for ever and I want to make sure all my replace will work the first time. What can I do to do this kind of operation?

Here's some example of my ereg(i)

if(eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip)) { /* ... */}
if (eregi($regexp, $label, $match)) { /* ... */}
$string = eregi_replace("[[:space:]]+", ' ', $string);

Thanks

Tech4Wilco
  • 6,740
  • 5
  • 46
  • 81

2 Answers2

12
#!/bin/bash
perl -p -i -e "s/eregi_replace *\\( *\"([^\@]+?)(?<\!\\\\)\", */preg_replace(\"\@\\1\@i\", /g" $1
perl -p -i -e "s/eregi_replace *\\( *\'([^\@]+?)(?<\!\\\\)\', */preg_replace(\'\@\\1\@i\', /g" $1
perl -p -i -e "s/ereg_replace *\\( *\"([^\@]+?)(?<\!\\\\)\", */preg_replace(\"\@\\1\@\", /g" $1
perl -p -i -e "s/ereg_replace *\\( *\'([^\@]+?)(?<\!\\\\)\', */preg_replace(\'\@\\1\@\', /g" $1
perl -p -i -e "s/eregi *\\( *\"([^\@]+?)(?<\!\\\\)\", */preg_match(\"\@\\1\@i\", /g" $1
perl -p -i -e "s/eregi *\\( *\'([^\@]+?)(?<\!\\\\)\', */preg_match(\'\@\\1\@i\', /g" $1
perl -p -i -e "s/ereg *\\( *\"([^\@]+?)(?<\!\\\\)\", */preg_match(\"\@\\1\@\", /g" $1
perl -p -i -e "s/ereg *\\( *\'([^\@]+?)(?<\!\\\\)\', */preg_match(\'\@\\1\@\', /g" $1

Here's a little bash script that I use. Someone with more time than me can probably squash all of this into less (1?) regular expressions, but it should do the trick. Feel free to replace @ with your delimiter of choice. Just paste this into a file, chmod +x it, and then call it, passing the file as an argument.

If you need to use it en masse, something like this should suffice:

find /path/to/your/project -name '*.php' -exec foo {} \;

Where foo is whatever you named the bash script.

Note: This isn't perfect, so you'll still need to manually change any fringe cases that it misses, but it will still save you a lot of work. Also note that this does in-place file edits.

FtDRbwLXw6
  • 27,774
  • 13
  • 70
  • 107
  • 1
    What if he is trying to match an email with ereg? I would suggest to use `~` as the delimiter instead. – Alix Axel Sep 27 '11 at 21:09
  • Variables and multiline patterns are also not covered by this. – Alix Axel Sep 27 '11 at 21:16
  • Without knowing what he's using regexes to match in his project, no suggested delimiter is better or worse than another (especially since I noted that he should replace it with his delimiter of choice). He may very well only be matching stuff with a lot of `~`s and no `@`s. – FtDRbwLXw6 Sep 27 '11 at 21:18
  • @Alix: Did you miss the **Note**? – FtDRbwLXw6 Sep 27 '11 at 21:20
  • Sure, I didn't payed attention to anything after your code, +1. – Alix Axel Sep 27 '11 at 21:21
  • @drrcknlsn: I get this error: Sequence (?<\...) not recognized in regex; marked by <-- HERE in m/eregi_replace *\( *"([^\@]+?)(?<\ <-- HERE !\\)", */ at -e line 1. – Tech4Wilco Sep 28 '11 at 12:19
  • @Tech4Wilco: Did you modify the script at all? It works fine for me. Changing the quotes will mess it up. The sequence `(?<!` is a negative lookbehind. It's written as `(?<\!` to escape the `!`, which has special meaning in bash. I suppose you could try not escaping it and see if that works for you. – FtDRbwLXw6 Sep 28 '11 at 18:17
  • I use the code I put in my question and execute your code. I will try – Tech4Wilco Sep 28 '11 at 19:36
0

replacing the actual ereg call would be a fairly simple matter of doing a search/replace operation. But actually fixing up your pattern to include the delimiters that preg requires is somewhat non-trivial. You can easily do:

$newcode = str_replace('eregi("', 'preg_match("/', $oldcode));

but then you'll still have to find where the pattern ends to add a delimiter there, as well as the i modifier. And you'd have to do this for every variant of ereg calls as well.

Marc B
  • 356,200
  • 43
  • 426
  • 500