[英]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. 然后使用unshift将
main
的当前值添加到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.