【问题标题】:Perl/Sed replace all matches in capture group with lowercase versionPerl/Sed 用小写版本替换捕获组中的所有匹配项
【发布时间】:2019-12-02 00:18:42
【问题描述】:

我需要将我在 php 应用程序中的所有包含替换为它们的小写等效项。我正在将旧版应用程序转换为 Docker,并且该应用程序是在 windows 中构建的。

我有以下我测试过的正则表达式

(include.+)["'](\w+\.php)["'](.*)

我已经尝试将它放入一个像这样的单行 perl 命令中

perl -p -i -e '/(include.+)[\"\'](\w+\.php)[\"\'](.*)/\1\'\L\2\'\E\3/ `find ./ -name *.php`

但我得到一个错误

('L2' 之前缺少运算符?) Bareword 在 -e 第 1 行的“'L2'E3”附近找到操作员预期的位置 (E3 之前缺少运算符?) -e 第 1 行,行尾的未知正则表达式修饰符“/1” -e 第 1 行的语法错误,靠近 "/(include.+)[\"](w+.php)"'/1'L2'" -e 的执行由于编译错误而中止。

我只需要用$1'{lowercase $2}'$3 替换匹配的字符串,但我不是perl 或sed 向导。

编辑

几个php include语句的例子

include "something.php";
include_once "something.php";
include("SomethingElse.php");
include ('Something.php');
include_once("something.php");
include_once ("something.php");

【问题讨论】:

  • 在 bash 的单引号中,反斜杠没有特殊含义。您不能在单引号中包含单引号。 '/(include.+)["'\'']...
  • 另外find 命令可以将不区分大小写的文件名与-iname 匹配。
  • 您能否展示一些要处理的实际include 语句示例? (一方面,'name.php' 可以跟随什么?)我们如何提供无需任何测试用例就能“工作”的东西? :)
  • edit 您的问题,以根据您发布的示例输入显示预期输出。
  • @choroba 出于好奇,显然有人可以使用 bash 的 $'...' 引用(那美元是真的!)以允许在内部添加一些 'perl -wE$'say "\'hi\'"'(我发现我还必须转义 ' 才能显示,否则解析得很好但 ' 不会打印)。

标签: php bash perl sed zsh


【解决方案1】:

要将include 语句中的内容小写,就地更改输入文件

perl -i.bak -wpe's/include.*\K (([\x22\x27]) \w+\.php \g{-1})/\L$1/x;' file

使用提供include 语句的文件进行测试。

注意事项:

  • 引号下名称前面的include.* 匹配(以标识该行),但随后与\K 一起删除,这样我们就不必在替换部分中捕获和复制它。请参阅“Lookaround Assertionsin Extended Patterns in perlre for \K

  • 引号"' 在字符类中使用\x22\x27 匹配(使用文字引号很棘手)。然后使用(相对)backreference\g{-1} 匹配结束引号,因此它必须与开始的相同

  • 首先捕获的整个'AbC.php'(所以在$1 中)用\L sequence 小写。这是在任何interpolated constructs

  • 中都有效的少数逃逸方法之一
  • 考虑添加锚点/^\s*(带有可选空格),以仅匹配字符串开头

  • /x 修饰符允许在正则表达式中使用空格(和 cmets)以提高可读性

我将.bak 添加到标记以保留备份,并添加-w 以打印警告。

【讨论】:

  • @richbai90 我确实有一个错字——有\27 而不是预期的\x27。呃。固定
  • idk 如果在 perl 中也是如此,但在 awk 中,我们避免使用十六进制 \x27,而使用八进制 \047,原因在 awk.freeshell.org/PrintASingleQuote 中讨论。
  • @EdMorton 有趣,感谢您的评论和链接。看来(通过链接中链接的 awk-manual 页面)这种awk 实践的起源可以追溯到gawk,它允许“失控”(我的术语“...允许两个以上连续hex bytes..." 来自手册)十六进制序列,导致问题。显然在 Perl 中不是问题,其中“... 序列\x。后面紧跟两个十六进制数字形成一个数字,或者一个任意长度的十六进制数字用花括号括起来。” [...]
  • @EdMorton [...] 上面的引用来自perlrebackslash 中的“十六进制转义”部分。似乎八进制在 Perl 中可能会变得不那么无忧无虑,因为传统的 \123 序列可能以不需要的方式解释(在 5.14+ Perls 中,\o{...} 形式是安全的)。这在perlrebackslash 中的“八进制转义”部分讨论,在十六进制(引用)部分之前。
  • 所以在没有 /e 限定符的情况下添加 \L 会使其小写!.. 很高兴知道
【解决方案2】:

编辑: 接受的答案确实解决了问题,下面的脚本也可以工作,为了后代保留它。

我无法让@zdim 回答工作,但从他的回答和一些 cmets 中借用我能够得到以下命令来做我需要的事情

find ./ -name *.php -print0 | xargs -0 perl -i.bak -wpe "s/(include.+)[\"'](\w+\.php)[\"'](.*)/\1\x27\L\2\x27\3/"

【讨论】:

    猜你喜欢
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 2017-05-02
    • 1970-01-01
    相关资源
    最近更新 更多