regex - 带组的 Perl 正则表达式替换

标签 regex linux perl ksh

我有以下 JSON 输入

... "somefield":"somevalue", "time":"timevalue", "anotherfield":"value" ...

在我的 KornShell (ksh) 脚本中,我希望用我的值替换时间值。所以我使用组创建了这个正则表达式,效果很好

data=`cat somefile.json`
echo $data | perl -pe "s|(.*time\"\s*\:\s*\").*?(\".*)|\1%TIME%\2|g" | another-script.sh

... "somefield":"somevalue", "time":"%TIME%", "anotherfield":"value" ...

但是...我不能使用数字作为替代,因为 Perl 使用数字来定义组..所以这个显然不起作用:

perl -pe "s|(.*time\"\s*\:\s*\").*?(\".*)|\120:00:00\2|g"

我可以通过两步替换来克服这个问题,

perl -pe "s|(.*time\"\s*\:\s*\").*?(\".*)|\1%TIME%\2|g" | perl -pe "s|%TIME%|20:00:00|"

... "somefield":"somevalue", "time":"20:00:00", "anotherfield":"value" ...

但我确信有更好、更优雅的方式来做到这一点。

最佳答案

Perl 不使用 \1用于替代。如果你启用了警告(例如,使用 perl -w ),Perl 会告诉你它是 $1。 .可以通过添加 { 来消除周围数字的歧义。 } :

perl -pe 's|(.*time"\s*:\s*").*?(".*)|${1}20:00:00$2|g'

(我还从正则表达式中删除了所有多余的反斜杠。)

另一方面,匹配 .* 有什么意义?如果你只是想自己更换它?难道就不能

perl -pe 's|(time"\s*:\s*").*?(")|${1}20:00:00$2|g'

?

我不太喜欢.*.*? .如果您尝试匹配带引号的字符串的内部,最好是具体的:

perl -pe 's|(time"\s*:\s*")[^"]*(")|${1}20:00:00$2|g'

我们没有尝试验证输入字符串,所以现在真的没有理由去匹配最终的 " (并自行替换):

perl -pe 's|(time"\s*:\s*")[^"]*|${1}20:00:00|g'

如果你的 Perl 不是很老 (5.10+),你可以使用 \K “保留”字符串的前导部分,即不将其包含在匹配中:

perl -pe 's|time"\s*:\s*"\K[^"]*|20:00:00|g'

现在只有[^"]*部分将被替换,使我们不必进行任何捕获。

关于regex - 带组的 Perl 正则表达式替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50266979/

相关文章:

python - Pandas 在与正则表达式匹配的列中用零替换负值

javascript - 接受数字并在文本字段中清空的指令

linux - 如何在 Linux 上卸载 perl

perl - 多重继承 - 选择了错误的重载

regex - 如何用正则表达式拆分 ruby 字符串?

javascript - 允许小写的正则表达式

linux - 出现未知错误 : Chrome failed to start: exited abnormally.(未知错误:DevToolsActivePort 文件不存在)

linux - 如果第一个是 '/opt/lampp/lampp start',rc.local 不运行第二个脚本

python 脚本参数在 Hudson Execute Shell 步骤中被误解

regex - Perl:将字符添加到行的开头