Dayo
Dayo

Reputation: 12775

Bash/Perl Multiline Regex Issue

Trying to apply some formatting a some files in a bash script and after a lot of web searches and trial / error, I came up with this using perl regexes as I need it be Mac / Linux compatible:

#!/bin/sh
FILES="$(find . -type f -name '*.php')"
for FILE in $FILES
do
    # 1. Add blank line after "global $XYZ" calls
    RET=$(perl -i -pe 's/^(\s*)global(\s)(.+);(\s*)$/$1global$2$3;\n\n\n/' $FILE)

    # 2. Add blank line before "$query" calls
    RET=$(perl -i -pe 's/\$query(\s+)(\.?=)/\$query $2/' $FILE)
    RET=$(perl -i -pe 's/^(\s*)\$query (\.?=)/\n$1\$query $2/' $FILE)

    # 3. Add blank line before "$ret" calls
    RET=$(perl -i -pe 's/\$ret(\s+)=/\$ret =/' $FILE)
    RET=$(perl -i -pe 's/^(\s*)\$ret =/\n$1\$ret =/' $FILE)

    # 4. Add blank line after single line "$ret" calls
    RET=$(perl -i -pe 's/^(\s*)\$ret(.+);(\s*)$/$1\$ret$2;\n/' $FILE)

    # 5. Add blank line before "list" calls
    RET=$(perl -i -pe 's/^(\s*)list\(/\n$1list(/' $FILE)

    # 6. Add blank line after single line "list" calls
    RET=$(perl -i -pe 's/^(\s*)list(.+);(\s*)$/$1list$2;\n/' $FILE)

    # 7. Add blank line after closing braces
    RET=$(perl -i -pe 's/^(\s*)\}(\s*)$/$1\}$2\n/' $FILE)

    # 8. Add blank line after closing multiline statements
    RET=$(perl -i -pe 's/^(\s*)\);(\s*)$/$1\);$2\n/' $FILE)

    # 9. Remove superflous blank lines
    RET=$(perl -i -0pe 's/(\n\s*){2,}(\n\s*)/\n$2/gs' $FILE)
    RET=$(perl -i -0pe 's/(\s*)(\/\/.+)(\n\s*){2,}$/$1$2\n/gs' $FILE)
done

It seems to generally work but the very last regex does not seems to kick in although I have tested it with online regex testers and it matches there.

I suspect it may be related to the /g modifier in the previous run but not sure.

Basically, I want to fix instances of blank lines after single line comments so that ...

  // Some Comment

  $ret = "XYZ";

is shown as ...

  // Some Comment
  $ret = "XYZ";

As said, the whole thing just works as if the regex is not there.

Upvotes: 0

Views: 134

Answers (1)

Håkon Hægland
Håkon Hægland

Reputation: 40718

Here is an example of how you can write the script as a single perl script:

use strict;
use warnings;
use File::Find::Rule;

my @files = File::Find::Rule->new->file->name('*.php')->in('.');
@ARGV = @files;
$^I = '.bak';  # suffix of backup file, see perldoc perlvar
while (<<>>) {
    s/^(\s*)global(\s)(.+);(\s*)$/$1global$2$3;\n\n\n/;
    s/\$query(\s+)(\.?=)/\$query $2/;
    s/^(\s*)\$query (\.?=)/\n$1\$query $2/;
    s/\$ret(\s+)=/\$ret =/;
    s/^(\s*)\$ret =/\n$1\$ret =/;
    s/^(\s*)\$ret(.+);(\s*)$/$1\$ret$2;\n/;
    s/^(\s*)list\(/\n$1list(/;
    s/^(\s*)list(.+);(\s*)$/$1list$2;\n/;
    s/^(\s*)\}(\s*)$/$1\}$2\n/;
    s/^(\s*)\);(\s*)$/$1\);$2\n/;
    print;
}
@ARGV = @files;
local $/ = undef; # Read the whole file
while (<<>>) {
    s/(\n\s*){2,}(\n\s*)/\n$2/gs;
    s/^(\s*)(\/\/.+?)(\n\s*){2,}/$1$2\n/gs;
    print;
}

Upvotes: 4

Related Questions