【问题标题】:Use ~ in Perl search and replace在 Perl 中使用 ~ 搜索和替换
【发布时间】:2017-01-03 06:35:49
【问题描述】:

我想用用户输入生成的字符串替换目录下所有文件中的占位符。这个输入可以包含/ : . ~

我选择 Perl 来完成这项任务。

perl -p -i -e "s/__MY_PLACEHOLDER__/$user_input/g" `find my_dir -type f -print0 | xargs -0`

现在,~ 是 Perl 中的保留字符。我怎样才能在$user_input 中逃脱~\~ 不起作用。

【问题讨论】:

  • 我打算提出 this question 作为副本,但我只是不喜欢接受的答案。您实际上结合了两个常见(但很好!)的问题:1)如何将 shell 变量传递给 Perl?和 2)如何在正则表达式中转义特殊字符?我找不到同时解决这两个问题的合适问题,所以也许这可以成为一个新的规范问题。
  • 您应该始终在 *nix 上将 Perl 单行语句用单引号括起来。意外地插入 shell 变量或触发历史命令太容易了(例如,perl -e"s!foo!bar!" 在 bash 中出现 "bash: !foo!bar!": event not found 错误)。您应该使用 Perl 的 %ENV 散列或将 bash 变量作为参数传递给 Perl 脚本。有几个不错的帖子,我会尽力为您找到它们。
  • 我要赶紧指出,当find 定位包含空格的文件时,您的perl 不会按照您的预期执行。
  • @DravSloan 这是真的。我通过我的目录的命名约定来解决这个问题——这适用于我的特殊用例。但为了给其他人留下可重用的解决方案,可接受的解决方案必须适用于名称中也包含空格的文件。
  • 为什么不find my_dir -type f -exec perl -i -pe 'commands' {} +

标签: perl replace


【解决方案1】:

实际上,~ 在双引号字符串字面量(例如s/// 的替换表达式)中并不特殊。然而,其他一些是特别的。在您列出的四个字符中,// 用作分隔符时是特殊的,就像这里的情况一样。


不要试图从 shell 生成 Perl 代码!使用以下方法之一:

export $user_input
perl -i -pe's/__MY_PLACEHOLDER__/$ENV{user_input}/g'

USER_INPUT=$user_input perl -i -pe's/__MY_PLACEHOLDER__/$ENV{USER_INPUT}/g'

perl -i -pe'
   BEGIN { $user_input = shift }
   s/__MY_PLACEHOLDER__/$user_input/g
' "$user_input"

顺便说一句,你真的错过了xargs的重点!

perl ... `find my_dir -type f -print0 | xargs -0`

没有什么不同
perl ... `find my_dir -type f`

你想要的是

find my_dir -type f -print0 | xargs -0 perl ...

这会将文件名传递给perl unmangled。如有必要,它甚至会使用不同批次的参数多次调用perl,以避免达到命令行长度限制。

【讨论】:

    猜你喜欢
    • 2019-05-05
    • 1970-01-01
    • 2018-08-21
    • 2017-01-05
    • 2019-01-12
    • 2021-01-31
    • 2019-10-14
    • 2020-11-22
    • 2020-04-29
    相关资源
    最近更新 更多