【问题标题】:Best way to test perl -pi -e one-liner before execution?在执行之前测试 perl -pi -e one-liner 的最佳方法?
【发布时间】:2021-06-10 17:52:10
【问题描述】:

我不知道任何 Perl,但我偶尔会使用“perl pie”(perl -pi -e)进行批量正则表达式查找和替换,例如将文件夹perl -pi -e 's|a|e|g' *.txt中的所有.txt文件中的a更改为e

有没有办法进行“试运行”以便我可以预览更改?我经常使用具有正/负前瞻/后视、组引用等的中等复杂的正则表达式,而且我通常不能 100% 确定我在第一次运行时就正确。 很棒有类似 rename.pl-n 标志的东西,它不会改变任何东西,只会输出已经做出的改变。

目前,我的策略是只使用接受 Perl 正则表达式的ack,以确保我的匹配字符串正确,然后从那里开始。有没有更好的办法?像rename -n这样的吗?

如果我错过了一些很棒的东西,也可以接受 perl 以外的东西,尽管我偏爱它的正则表达式格式。

非常感谢!

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    只需从您的 perl 代码中删除 -i 参数即可进行试运行。

    perl -pe 's|a|e|g' *.txt
    

    来自perl --help

    -i[extension]     edit <> files in place (makes backup if extension supplied)
    

    打印发生替换的特定行。

    $ cat file
    abcd
    cbcb
    foo
    $ perl -nle 'print if s|a|e|g' file
    ebcd
    

    【讨论】:

    • 感谢您的回复,但如上所述,我只想输出更改(而不是整个文件内容)。
    • 如果要打印发生更改的特定行,则需要添加 -n 而不是 -p 参数。 perl -nle 'print if s|a|e|g' file
    • 太好了,谢谢!以下通过显示正在匹配的文件使其更接近 rename.pl 输出,但这肯定回答了问题。 perl -ne 'if (s|a|e|g) { print "$ARGV\t"; print }' *.txt
    【解决方案2】:

    两种解决方案。

    1. 删除-i参数,以便将修改后的文件打印到控制台

    2. 指定备份扩展-i.bak,以便您可以观察更改并在必要时恢复

    无论哪种方式,我都会在不使用 glob *.txt 的情况下进行测试,而是在单个文件上工作,直到您确定它工作正常为止。

    我可能会倾向于使用单个文件的第二个选项。这样您就可以轻松地发送diff 来观察发生的变化。

    $ perl -i.bak -pe 's|a|e|g' sample.txt
    $ diff sample.txt sample.txt.bak
    

    【讨论】:

    • 这更接近我所希望的,因为diff 只会输出更改。我认为最好的答案可能是第一种和第二种解决方案的组合,for f in *.txt; do diff &lt;(perl -pe 's|a|e|g' "$f") "$f"; done
    【解决方案3】:

    基于@8henrie's comment,以下显示了 git 所做的更改:

    for f in *.txt; do perl -pe 's/a/e/g' "$f" | git diff --no-index -- - "$f"; done

    检查后,您可以使用以下命令执行实际替换:

    perl -pi -e 's/a/e/g' *.txt

    【讨论】:

      猜你喜欢
      • 2021-03-15
      • 2012-08-01
      • 1970-01-01
      • 2016-11-22
      • 2014-07-31
      • 1970-01-01
      • 2014-05-08
      • 2014-03-19
      • 2013-09-26
      相关资源
      最近更新 更多