正则表达式匹配中的 Perl 循环
Perl loop within regex match
看看这个命令:
perl -0777ne 'print "$&\n\n" while /"(QueryString|Params)":\[(\{"Name":".*?", ?"Value":".*?"\},? ?)*\]/g;' myfile.json
它 iterate through each match 的 json 个字符串如:
{
"Some": "Random stuff",
"QueryString": [
{ "Name": "IsOrdered", "Value": "1" },
{ "Name": "TimeStamp", "Value": "11654116426247" }
],
"Params": [
{ "Name": "ClassName", "Value": "PRODUCT" },
{ "Name": "ListID", "Value": "Products" },
{ "Name": "Mode ", "Value": "1" },
{ "Name": "Dept" , "Value": "5" },
{ "Name": "HasPrevOrder", "Value": "" }
],
"And": {
"QueryString":[]
},
"More": "like",
"More+": "this"
}
现在我的问题是如何遍历 Name/Value 对的每个正则表达式匹配,并将它们连接在一起回到正常的 http 查询字符串?
例如,对于
"QueryString":[{"Name":"IsOrdered", "Value":"1"}, {"Name":"TimeStamp", "Value":"11654116426247"}]
联合输出应该是
"QueryString":"IsOrdered=1&TimeStamp=11654116363378"
和"QueryString":[]
到"QueryString":""
请注意,我想进行正则表达式匹配和替换,因为我需要保留其余的 JSON 组件。我说的 JSON 文件实际上是一个 har 文件。它退出了一个复杂的结构,然而
"(QueryString|Params)":\[(\{"Name":".*?", ?"Value":".*?"\},? ?)*\]
就是我要替换的全部。仅此而已。
我会使用 jq
。
jq '
walk(
if type == "object" then
(
( .QueryString, .Params ) | select( . != null )
) |= (
map( @uri "\( .Name )=\( .Value )" ) | join("&")
)
else
.
end
)
'
Demo 在 jqplay
这会修改所有包含具有这些键之一的元素的对象。我通常更喜欢更有针对性的东西(不仅仅是为了效率原因,而是为了避免不小心更改不应该更改的内容),但我对 HAR 格式的了解不足,无法做到这一点。
下面是一个也能完成任务的 Perl 程序:
use feature qw( say );
use Cpanel::JSON::XS qw( decode_json encode_json );
use URI::Escape qw( uri_escape_utf8 );
sub transform {
for ( @_ ) {
$_ =
join "&",
map {
join "=",
map uri_escape_utf8( $_ ),
$_->@{qw( Name Value )}
}
@$_;
}
}
sub fix {
my $x = shift;
my $type = ref( $x );
if ( $type eq "HASH" ) {
for my $k ( keys( %$x ) ) {
for my $v ( $x->{ $k } ) {
if ( $k eq "QueryString" || $k eq "Params" ) {
transform( $v );
} else {
fix( $v );
}
}
}
}
elsif ( $type eq "ARRAY" ) {
fix( $_ ) for @$x;
}
}
local $/;
while ( <> ) {
my $data = decode_json( $_ );
fix( $data );
say( encode_json( $data ) );
}
看看这个命令:
perl -0777ne 'print "$&\n\n" while /"(QueryString|Params)":\[(\{"Name":".*?", ?"Value":".*?"\},? ?)*\]/g;' myfile.json
它 iterate through each match 的 json 个字符串如:
{
"Some": "Random stuff",
"QueryString": [
{ "Name": "IsOrdered", "Value": "1" },
{ "Name": "TimeStamp", "Value": "11654116426247" }
],
"Params": [
{ "Name": "ClassName", "Value": "PRODUCT" },
{ "Name": "ListID", "Value": "Products" },
{ "Name": "Mode ", "Value": "1" },
{ "Name": "Dept" , "Value": "5" },
{ "Name": "HasPrevOrder", "Value": "" }
],
"And": {
"QueryString":[]
},
"More": "like",
"More+": "this"
}
现在我的问题是如何遍历 Name/Value 对的每个正则表达式匹配,并将它们连接在一起回到正常的 http 查询字符串?
例如,对于
"QueryString":[{"Name":"IsOrdered", "Value":"1"}, {"Name":"TimeStamp", "Value":"11654116426247"}]
联合输出应该是
"QueryString":"IsOrdered=1&TimeStamp=11654116363378"
和"QueryString":[]
到"QueryString":""
请注意,我想进行正则表达式匹配和替换,因为我需要保留其余的 JSON 组件。我说的 JSON 文件实际上是一个 har 文件。它退出了一个复杂的结构,然而
"(QueryString|Params)":\[(\{"Name":".*?", ?"Value":".*?"\},? ?)*\]
就是我要替换的全部。仅此而已。
我会使用 jq
。
jq '
walk(
if type == "object" then
(
( .QueryString, .Params ) | select( . != null )
) |= (
map( @uri "\( .Name )=\( .Value )" ) | join("&")
)
else
.
end
)
'
Demo 在 jqplay
这会修改所有包含具有这些键之一的元素的对象。我通常更喜欢更有针对性的东西(不仅仅是为了效率原因,而是为了避免不小心更改不应该更改的内容),但我对 HAR 格式的了解不足,无法做到这一点。
下面是一个也能完成任务的 Perl 程序:
use feature qw( say );
use Cpanel::JSON::XS qw( decode_json encode_json );
use URI::Escape qw( uri_escape_utf8 );
sub transform {
for ( @_ ) {
$_ =
join "&",
map {
join "=",
map uri_escape_utf8( $_ ),
$_->@{qw( Name Value )}
}
@$_;
}
}
sub fix {
my $x = shift;
my $type = ref( $x );
if ( $type eq "HASH" ) {
for my $k ( keys( %$x ) ) {
for my $v ( $x->{ $k } ) {
if ( $k eq "QueryString" || $k eq "Params" ) {
transform( $v );
} else {
fix( $v );
}
}
}
}
elsif ( $type eq "ARRAY" ) {
fix( $_ ) for @$x;
}
}
local $/;
while ( <> ) {
my $data = decode_json( $_ );
fix( $data );
say( encode_json( $data ) );
}