简体   繁体   English

Perl正则表达式一个内衬无法正常工作

[英]Perl regex one liner not working correctly

I'm trying to do the following in a bash script to a file: 我正在尝试在bash脚本中对文件执行以下操作:

Before: 之前:

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

After: 后:

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

using this perl one liner: 使用此perl一个衬里​​:

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

Where $version holds the new version number and $json is the path to the file. $version保存新版本号,而$json是文件的路径。

It seems perl doesn't match, and I can't understand why. 似乎perl不匹配,我也不明白为什么。 Removing the \\[ does match, but I can't see what's wrong with that literal. 删除\\[确实匹配,但是我看不出该文字有什么问题。

Assuming that you can fix your JSON (a trailing comma is not allowed) I'd recommend to process this using a module, and in a script. 假设您可以修复JSON(不允许使用逗号结尾),建议您使用模块和脚本来处理。

An example with JSON , wrapped in a "one"-liner as asked 带有JSON的示例,按要求包装在“一个”内衬中

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

The very handy Path::Tiny is used to easily dump JSON output. 非常方便的Path :: Tiny用于轻松转储JSON输出。 I make the output file name by prefixing new_ to the input filename (available in $ARGV variable ), adjust as suitable. 我通过在输入文件名(将$ ARGV变量中提供 )前面添加new_作为输出文件名,并进行适当调整。

If installing a module is a problem for some reason you can instead simply print the JSON encoded string and redirect the output 如果由于某种原因安装模块有问题,您可以直接打印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

These produce the output file with {"archive":["3.3.0","3.2.2"],"main":"3.3.1"} 它们产生带有{"archive":["3.3.0","3.2.2"],"main":"3.3.1"}的输出文件

With the -0777 command switch the whole file is "slurped" into a scalar ( $_ ) and -M... loads the given module. 使用-0777 命令开关 ,整个文件被“打包”为标量( $_ ),并且-M...加载给定的模块。 Then we use decode_json , which JSON exports by default in its functional interface, to obtain a hashref with data. 然后,我们使用decode_json (它是JSON在其功能接口中默认导出的)来获取包含数据的hashref。

The current value of main is then added to the beginning of the arrayref in archive using unshift , and is then changed by bumping up its release/patch number, using a regex. 然后使用unshiftmain的当前值添加到archive arrayref的开头,然后使用正则表达式通过增加其发行版/补丁号来进行更改。

Finally the encode_json , also exported in JSON 's functional interface, is used to JSON-encode the hashref, what is dumped either with Path::Tiny to a file or to STDOUT for redirection. 最终,也在JSON的功能接口中导出的encode_json用于对hashref进行JSON编码,然后将其与Path::Tiny一起转储到文件或STDOUT进行重定向。


A word on the number of existing JSON modules is in order, prompted by comment by Grinnz. 由Grinnz发表评论,按顺序对现有JSON模块的数量进行了说明。

The JSON linked above will load the JSON::XS module, and if that is not installed then it falls back to the compatible pure-Perl one, JSON::PP . 上面链接的JSON将加载JSON :: XS模块,如果未安装该模块,则会回退到兼容的纯Perl JSON :: PP I'd recommend the XS module, which is much faster and proven in wide use. 我建议使用XS模块,该模块速度更快且已被广泛使用。

Another option is Cpanel::JSON::XS , the JSON::XS fork with a bug tracker and a list of bug fixes . 另一个选项是Cpanel :: JSON :: XS ,这是带有错误跟踪器和错误修复列表的JSON::XS分支。 I've happily used both without any issues. 我很高兴地使用了两者,没有任何问题。

To have these tried in order Cpanel:: then ::XS then ::PP , also with some improvements over JSON in how backends are loaded, use JSON::MaybeXS . 要按顺序依次尝试Cpanel:: ::XS ::PP ,并在后端加载方式方面对JSON进行了一些改进,请使用JSON :: MaybeXS

Note that none of these are in core. 请注意,这些都不是核心。

(now that Ihis question has been reopened and I can post an answer..) (现在,他的问题已经重新开放,我可以发布答案。)

Assuming you fix your data so it's valid JSON (Note the invalid trailing comma), this is an easy jq one-liner: 假设您修复了数据,使其成为有效的JSON(请注意无效的结尾逗号),这是一个简单的jq单行代码:

$ jq "{main: \"$version\", archive: [ .main, .archive[] ]}" "$json" > new.json
$ mv -f new.json "$json"

Just like with HTML and XML, using regular expressions to try to manipulate JSON is a mistake. 就像HTML和XML一样,使用正则表达式尝试操作JSON是一个错误。 Use a more appropriate tool. 使用更合适的工具。

Using jq to both move the main version number to the array archive and increment the last digit of the main version: 使用jq既可以将main版本号移动到阵列archive又可以将main版本的最后一位递增:

jq '.archive += [.main] |
    .main |= (split(".") | .[-1] |= (tonumber+1|tostring) | join("."))' file

The operator += adds a new value to the array archive . 运算符+=将新值添加到数组archive

The operator |= assigns a new value to main . 运算符|=main分配一个新值。 The last element of the splitted string is incremented by 1 and then reassembled. 分割后的字符串的最后一个元素加1,然后重新组合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM