我有以下 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/