1

我正在尝试重新格式化一些代码,特别是条件块,从在行尾使用逻辑运算符到行首,如下所示:

    if ($arg == true ||
        $arg != null &&
        $arg != 42
    ) {...}

    if ($arg == true
        || $arg != null
        && $arg != 42
    ) {...}

sed证明是不够的,所以我正在尝试perl,例如:

perl -i'' -pe 's/ (&&|\|\|)(\s+)/$2$1 /gs' $file

但是,我得到的结果是不正确的:

    if ($arg == true
||         $arg != null
&&         $arg != 42
    ) {...}

似乎(\s+)只捕获一个字符,所有剩余的空间都留在原来的位置。我尝试过的变体也失败了。

我究竟做错了什么?

4

4 回答 4

4

我能看到的问题是-p开关。它逐行读取输入文件的内容,并一次为每个文件执行正则表达式。这意味着该/s标志是无用的。该(\s+)部分匹配换行符,打印它,然后在下一行的开头打印您的条件,依此类推。

修复它读取整个内容并立即将正则表达式应用于所有内容:

perl -i'' -0777 -pe 's/ (&&|\|\|)(\s+)/$2$1 /g' $file

它产生:

if ($arg == true
    || $arg != null
    && $arg != 42
) {...}
于 2013-07-13T23:44:17.500 回答
3

如果您想认真考虑重新格式化 Perl,请下载并使用它附带Perl::Tidy的脚本。perltidy

于 2013-07-13T23:53:12.627 回答
2

您一次阅读一行,但您试图匹配跨越两行的文本。

$/简单的解决方案是通过设置为undefusing将整个文件加载到内存中-0777

perl -i -0777pe's/ (&&|\|\|)(\s+)/$2$1 /gs' "$file"
于 2013-07-13T23:45:18.833 回答
1

可能有更好的方法可以做到这一点,但这就是我所拥有的:

perl -pe 's/(&&|\|\|)\s*$/\n/; $p=$1; $m && s/^(\s*)/$1$m  /; $m=$p;' input

这不会读取整个文件,而是会记住前一行的任何结转。

于 2013-07-13T23:58:42.907 回答