首页 > 解决方案 > Perl 正则表达式一个衬里无法正常工作

问题描述

我正在尝试在 bash 脚本中对文件执行以下操作:

前:

{
    "main": "3.3.0",
    "archive":[
        "3.2.2"
    ]
}

后:

{
    "main": "3.3.1",
    "archive":[
        "3.3.0",
        "3.2.2"
    ]
}

使用这个 perl one liner:

perl -pi -e "s/\"main\"\: \"(.*?)(\".*)\[/\"main\": \"${version}\2\[\n\t\t\"\1\",/s" "$json"

where$version保存新版本号,$json是文件的路径。

似乎 perl 不匹配,我不明白为什么。删除\[确实匹配,但我看不出该文字有什么问题。

标签: regexbashperl

解决方案


假设您可以修复您的 JSON(不允许使用尾随逗号),我建议您使用模块和脚本来处理它。

一个带有JSON的示例,按照要求包装在“one”-liner 中

perl -MPath::Tiny -MJSON -0777 -wnE'
    my $hr = decode_json $_; 
    unshift @{$hr->{archive}}, $hr->{main}; 
    $hr->{main} =~ s/[0-9]+\.[0-9]+.\K([0-9]+)/$1+1/e; 
    path("new_".$ARGV)->spew(encode_json $hr)' 
' data.json

非常方便的Path::Tiny用于轻松转储 JSON 输出。我通过在输入文件名前加上前缀new_(在$ARGV 变量中可用)来制作输出文件名,并根据需要进行调整。

如果由于某种原因安装模块是一个问题,您可以简单地打印 JSON 编码的字符串并重定向输出

perl -MJSON -0777 -wnE'
    my $hr = decode_json $_; 
    unshift @{$hr->{archive}}, $hr->{main}; 
    $hr->{main} =~ s/[0-9]+\.[0-9]+.\K([0-9]+)/$1+1/e; 
    say encode_json $hr 
' data.json > new_data.json

这些产生输出文件   {"archive":["3.3.0","3.2.2"],"main":"3.3.1"}

使用-0777 命令开关,整个文件被“slurped”成一个标量($_)并-M...加载给定的模块。然后我们使用decode_json,它JSON在其功能接口中默认导出,以获取带有数据的 hashref。

然后使用unshift将当前值main添加到 arrayref 的开头,然后使用正则表达式通过增加其版本/补丁号来更改。archive

最后encode_json,也在JSON的功能接口中导出,用于对 hashref 进行 JSON 编码,将转储Path::Tiny到文件或 STDOUT 以进行重定向。


Grinnz 的评论提示了现有 JSON 模块的数量。

上面链接的JSON将加载JSON::XS模块,如果没有安装,那么它将回退到兼容的纯 Perl 模块JSON::PP。我推荐 XS 模块,它速度更快,并且经过广泛使用。

另一个选项是Cpanel::JSON::XSJSON::XS带有错误跟踪器和错误修复列表的分支。我很高兴地使用了这两种方法,没有任何问题。

要按顺序尝试这些,同时对后端的加载方式Cpanel::进行一些改进,请使用JSON::MaybeXS::XS::PPJSON

请注意,这些都不是核心。


推荐阅读