【问题标题】:Bash/Perl Multiline Regex IssueBash/Perl 多行正则表达式问题
【发布时间】:2019-03-04 18:51:32
【问题描述】:

尝试在 bash 脚本中对某些文件应用一些格式,经过大量网络搜索和试验/错误后,我使用 perl 正则表达式想出了这个,因为我需要它与 Mac / Linux 兼容:

#!/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

它似乎通常可以工作,但最后一个正则表达式似乎没有启动,尽管我已经使用在线正则表达式测试器对其进行了测试并且它在那里匹配。

我怀疑它可能与上一次运行中的 /g 修饰符有关,但不确定。

基本上,我想在单行 cmets 之后修复空行实例,以便 ...

  // Some Comment

  $ret = "XYZ";

显示为 ...

  // Some Comment
  $ret = "XYZ";

如前所述,整个事情就像正则表达式不存在一样。

【问题讨论】:

  • 请注意,您应该将m 修饰符添加到最后一个正则表达式以匹配使用$ 的行尾。如果不是,$ 将只匹配字符串的结尾。
  • .+ 是贪婪的。另外,重新排列,使\n 在空格之后。试试看:s/(\s*)(\/\/.+?\n)(\s*\n)/$1$2/gs
  • @HåkonHægland。谢谢,但它没有收到任何东西
  • 这应该是 one perl 脚本,而不是每个文件运行 perl 12 次。
  • 你没有;你编写一个 perl 脚本,然后调用它。整个 shell 循环被替换为 perl myScript.pl "${FILES[@]}"

标签: regex bash perl


【解决方案1】:

这是一个示例,说明如何将脚本编写为单个 perl 脚本:

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;
}

【讨论】:

  • 也许是&lt;&lt;&gt;&gt; 而不是&lt;&gt; 以避免安全漏洞
  • @jhnc 很好,是的,使用&lt;&lt;&gt;&gt; 来避免在允许文件名的文件上使用2-参数openrm -rfv *|
  • &lt;&lt;&gt;&gt; 是做什么的? Perl 的有趣之处在于,如果我在 Google 中搜索 perl "&lt;&lt;&gt;&gt;",我在前 10 个结果中找不到任何相关答案:(
  • @nowox 见perldoc perlop
  • @HåkonHægland。查找器中是否可以有多个扩展?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多