Search code examples
linuxperlrecursionreplaceregexp-replace

Perl regular expression to replace string recursively in multiple file groups, like "*.php" "*.html"


The following command is not working, does nothing:

sudo find /srv/my/directory -type f -iname '*.htm*' -iname '*.old1' -iname '*.php' | sudo xargs -iX sudo perl -p -i -e 's|\<\?php.*123456.*123456.*\?\>\r?\n\<\?php|<?php|g' 'X'

It does not replace anything in the files.

What is wrong?

SOLUTION:

sudo find /srv/my/directory -type f -iname '*.htm*' -or -iname '*.old1' -or -iname '*.php' | sudo xargs -iX sudo perl -0777 -p -i -e 's|\<\?php.*123456.*123456.*\?\>\r?\n\<\?php|<?php|g' 'X'

SOLUTION 2 (extends capability for multiple situations in regexp):

sudo find /srv/my/directory -type f -iname '*.htm*' -or -iname '*.old1' -or -iname '*.php' | sudo xargs -iX sudo perl -0777 -p -i -e 's@\<\?php.*123456.*123456.*\?\>(\r?\n|\#\!.*)\<\?php@<?php@gs' 'X'

Solution

    1. When specifying several conditions to find, they are by default connected by an implicit -and. No file can match -iname '*.old1' -and -iname '*.php'. You must specify -or explicitly.

    2. Unless told otherwise, perl -p reads the file line by line, so it can't match \n<. Use -0777 to read the whole file instead of processing it line by line.

     

    sudo find /srv/my/directory -type f \
        -iname '*.htm*' -or -iname '*.old1' -or -iname '*.php' \
        | sudo xargs -iX sudo perl -0777 -p -i \
            -e 's/<\?php.*123456.*123456.*\?>\r?\n<\?php/<?php/g' 'X'
    

    BTW, you don't need to backslash < and > in Perl regexes.