Perl正则表达式在线测试生效但单行命令替换无效果如何解决
问题原因及修正方案
核心问题点
- shell提前变量插值
你使用双引号包裹perl的替换表达式,shell会优先解析所有以$开头的内容为shell变量:
- 正则中的
\$log_path的转义符在双引号中对$的转义行为不稳定,最终传入perl的正则会出现变量缺失,无法匹配目标行 - 替换部分的
$1、$2、$3会被shell解析为当前环境的位置参数,默认值为空,就算匹配成功也无法完成正确替换
- 替换规则不匹配预期
你预期的结果是将/var/www/之后到下一个/之前的内容(也就是示例中的website)替换为test,但你原来的替换式保留了对应该部分的分组$2,最终会得到/var/www/test/website/administrator/logs,和预期不符 - 缺少原地修改参数
默认perl -p只会将处理后的内容输出到控制台,不会修改原文件,需要添加-i参数实现原地修改
修正后命令
推荐使用自定义正则分隔符避免路径转义,同时用单引号包裹表达式避免shell插值:
perl -i.bak -pe 's#(public\s\$log_path\s=\s'\''/var/www/)(.*?)(?=/)(.*)#$1test$3#' <file-name>.php
参数说明
-i.bak:原地修改目标文件,同时自动生成后缀为.bak的原文件备份,确认修改正确后可自行删除备份- 单引号包裹整个替换表达式:完全避免shell解析表达式内的
$变量,确保内容完整传入perl - 用
#作为正则分隔符:免除路径中/的转义,大幅提升可读性
验证效果
执行后目标行会被替换为你预期的结果:
public $log_path = '/var/www/test/administrator/logs';
内容的提问来源于stack exchange,提问作者jsjw
相关产品推荐
相关产品推荐

