regex - 如何在 perl 替换中转义 REPLACEMENT?

标签 regex perl bash replace escaping

如何使用 s// 运算符完全转义 perl 替换的 REPLACEMENT 部分? \Q\E 的工作方式如下所示:

对于上下文,当使用 perl 进行大型递归搜索并替换由 bash 脚本驱动的操作时会出现这种情况。这不是一个容易避免的情况。

以这个脚本为例:

$ cat example.sh
#!/bin/bash
set -v -x
EMAIL=user@example.org
echo "EMAIL = $EMAIL"
echo "Email address: here" | perl -p -e "s/here/$EMAIL/"
echo "Email address: here" | perl -p -e "s/here/\\Q$EMAIL\\E/"
echo "Email address: here" | perl -p -e "s/here/${EMAIL/@/\\@}/"

让我们运行它:

$ ./example.sh
EMAIL=user@example.org
+ EMAIL=user@example.org
echo "EMAIL = $EMAIL"
+ echo 'EMAIL = user@example.org'
EMAIL = user@example.org

到目前为止一切顺利。 shell 没有破坏任何东西,我们正在回应我们的期望。

echo "Email address: here" | perl -p -e "s/here/$EMAIL/"
+ echo 'Email address: here'
+ perl -p -e s/here/user@example.org/
Email address: user.org

好吧,那个时候替换没有被引用,所以字符串的 @example 部分被扩展(什么都没有)并且有效地消失了。好吧,好吧,让我们和我们的好 friend \Q\E 一起逃避吧:

echo "Email address: here" | perl -p -e "s/here/\\Q$EMAIL\\E/"
+ echo 'Email address: here'
+ perl -p -e 's/here/\Quser@example.org\E/'
Email address: user\.org

好吧,这是出乎意料的! \Q\E 引用了 .,但是他们没有转义 @example 部分!这是怎么回事?

echo "Email address: here" | perl -p -e "s/here/${EMAIL/@/\\@}/"
+ echo 'Email address: here'
+ perl -p -e 's/here/user\@example.org/'
Email address: user@example.org

好吧,这终于奏效了,但这只是因为我们使用 bash 模式扩展来进行搜索和替换。它在这种特殊情况下有效,因为这是一个电子邮件地址。在更一般的情况下,对所有可能的替换元字符执行此操作将非常繁琐。

那么,在使用 s// 运算符时,如何完全转义 perl 替换的 REPLACEMENT 部分?是否可以?一定有一个我想念的把戏。 =)

已解决

ysth 的回答建议使用 s''',它解决了这个简单的例子,但我不能在我的实际代码中使用它,因为我在实际使用中需要反向引用。然而,ysth 的回答和 TLP 的评论都建议使用 $ENV{...}。据我所知,到目前为止,这在我的实际用例中非常有效,它必须能够使用反向引用。

这是上面示例的更新版本。

$ cat example-new.sh
#!/bin/bash
set -v -x
EMAIL=user@example.org
# Don't touch my delimiters!
echo "Email address goes >>>>>>here<<" | perl -p -e 's/(>+)here(<+)/$1$ENV{EMAIL}$2/'

运行时它按预期工作:

$ ./example-new.sh
EMAIL=user@example.org
+ EMAIL=user@example.org
# Don't touch my delimiters!
echo "Email address goes >>>>>>here<<" | perl -p -e 's/(>+)here(<+)/$1$ENV{EMAIL}$2/'
+ echo 'Email address goes >>>>>>here<<'
+ perl -p -e 's/(>+)here(<+)/$1$ENV{EMAIL}$2/'
Email address goes >>>>>>user@example.org<<

最佳答案

\Q\E 应用于变量插值的结果,因此您不能阻止@example 以这种方式进行插值。

但是你可以使用单引号:

#!/bin/bash
set -v -x
EMAIL=user@example.org
echo "Email address: here" | perl -p -e "s'here'$EMAIL'"

或者,如果电子邮件地址可能包含 '\\,让 perl 从环境中获取 $EMAIL:

export EMAIL=user@example.org
echo "Email address: here" | perl -p -e 's/here/$ENV{EMAIL}/'

关于regex - 如何在 perl 替换中转义 REPLACEMENT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20183148/

相关文章:

regex - Url Rewrite HTTPS -> HTTP 特定页面除外 (IIS 7)

java - 在不同索引处的两个字符串中查找匹配字符

perl - 如何从 Perl 创建或读取 OpenOffice 电子表格?

windows - 使用 Cygwin 进行 FFMPEG 构建错误 cmp : command not found

linux - 将每 N 行输入放入一个新列

linux - 如何比较bash中的2个范围列表?

python - 我应该使用正则表达式来获取文件名吗?

javascript - 是否可以/建议使用正则表达式解析我的用户输入字符串?

Perl 中的正则表达式不匹配

perl - 有没有办法在 Perl 中重载/拦截对重载对象的函数调用?