如何避免 Perl 正则表达式替换中的警告?
How to avoid warnings in Perl regex substitution with alternatives?
我有这个正则表达式。
$string =~ s/(?<!["\w])(\w+)(?=:)|(?<=:)([\w\d\.+=\/]+)/""/g;
正则表达式本身工作正常。
但是由于我正在替换备选方案(并且在全球范围内),所以我总是收到 $1 或 $2 未初始化的警告。这些警告使我的日志文件混乱。
我该怎么做才能更好地避免此类警告?
还是我关闭警告的最佳选择?我对此表示怀疑。
附带问题:是否有更好的方法可以做到这一点,例如根本不使用正则表达式?
我正在做的是修复 JSON,其中某些 key:value 对没有双引号,并且 JSON 模块在尝试解码时不喜欢它。
有几种方法可以解决这个问题。
如果您打算使用捕获组:
当捕获整个交替的每个子句时。
将捕获组合并为 1 并将该组移出。
( # (1 start)
(?<! ["\w] )
\w+
(?= : )
|
(?<= : )
[\w\d\.+=/]+
) # (1 end)
s/((?<!["\w])\w+(?=:)|(?<=:)[\w\d\.+=\/]+)/""/g
使用分支重置构造(?| aaa )
。
这将导致每次交替中的捕获组开始对其组进行编号
从同一点。
(?|
(?<! ["\w] )
( \w+ ) # (1)
(?= : )
|
(?<= : )
( [\w\d\.+=/]+ ) # (1)
)
s/(?|(?<!["\w])(\w+)(?=:)|(?<=:)([\w\d\.+=\/]+))/""/g
使用 Named 捕获可重复使用的组(类似于分支重置)。
在每次交替中,重复使用相同的名称。将不相关的组设为空组。
这通过在替换中使用 name 而不是数字来实现。
(?<! ["\w] )
(?<V1> \w+ ) # (1)
(?<V2> ) # (2)
(?= : )
|
(?<= : )
(?<V1> ) # (3)
(?<V2> [\w\d\.+=/]+ ) # (4)
s/(?<!["\w])(?<V1>\w+)(?<V2>)(?=:)|(?<=:)(?<V1>)(?<V2>[\w\d\.+=\/]+)/"$+{V1}$+{V2}"/g
命名替换和分支重置这两个概念可以合并
如果交替包含超过 1 个捕获组。
下面的示例使用捕获组编号。
理论是你将 dummy 个捕获组放在
的每个交替中
"pad" 分支等于单个交替中的最大组数。
确实,必须这样做以避免 Perl 正则表达式中可能导致崩溃的错误。
(?| # Branch Reset
# ------ Br 1 --------
( ) # (1)
( \d{4} ) # (2)
ABC294
( [a-f]+ ) # (3)
|
# ------ Br 2 --------
( :: ) # (1)
( \d+ ) # (2)
ABC555
( ) # (3)
|
# ------ Br 3 --------
( == ) # (1)
( ) # (2)
ABC18888
( ) # (3)
)
s/(?|()(\d{4})ABC294([a-f]+)|(::)(\d+)ABC555()|(==)()ABC18888())/""/g
您可以尝试使用 Cpanel::JSON::XS's relaxed mode, or JSONY,解析几乎-JSON,然后使用 Cpanel::JSON::XS 写出常规 JSON。根据您的输入数据到底出了什么问题,一个或另一个可能会更好地理解它。
use strict;
use warnings;
use Cpanel::JSON::XS 'encode_json';
# JSON is normally UTF-8 encoded; if you're reading it from a file, you will likely need to decode it from UTF-8
my $string = q<{foo: 1,bar:'baz',}>;
my $data = Cpanel::JSON::XS->new->relaxed->decode($string);
my $json = encode_json $data;
print "$json\n";
use JSONY;
my $data = JSONY->new->load($string);
my $json = encode_json $data;
print "$json\n";
我有这个正则表达式。
$string =~ s/(?<!["\w])(\w+)(?=:)|(?<=:)([\w\d\.+=\/]+)/""/g;
正则表达式本身工作正常。
但是由于我正在替换备选方案(并且在全球范围内),所以我总是收到 $1 或 $2 未初始化的警告。这些警告使我的日志文件混乱。
我该怎么做才能更好地避免此类警告? 还是我关闭警告的最佳选择?我对此表示怀疑。
附带问题:是否有更好的方法可以做到这一点,例如根本不使用正则表达式? 我正在做的是修复 JSON,其中某些 key:value 对没有双引号,并且 JSON 模块在尝试解码时不喜欢它。
有几种方法可以解决这个问题。
如果您打算使用捕获组:
当捕获整个交替的每个子句时。
将捕获组合并为 1 并将该组移出。( # (1 start) (?<! ["\w] ) \w+ (?= : ) | (?<= : ) [\w\d\.+=/]+ ) # (1 end)
s/((?<!["\w])\w+(?=:)|(?<=:)[\w\d\.+=\/]+)/""/g
使用分支重置构造
(?| aaa )
。
这将导致每次交替中的捕获组开始对其组进行编号
从同一点。(?| (?<! ["\w] ) ( \w+ ) # (1) (?= : ) | (?<= : ) ( [\w\d\.+=/]+ ) # (1) )
s/(?|(?<!["\w])(\w+)(?=:)|(?<=:)([\w\d\.+=\/]+))/""/g
使用 Named 捕获可重复使用的组(类似于分支重置)。
在每次交替中,重复使用相同的名称。将不相关的组设为空组。
这通过在替换中使用 name 而不是数字来实现。(?<! ["\w] ) (?<V1> \w+ ) # (1) (?<V2> ) # (2) (?= : ) | (?<= : ) (?<V1> ) # (3) (?<V2> [\w\d\.+=/]+ ) # (4)
s/(?<!["\w])(?<V1>\w+)(?<V2>)(?=:)|(?<=:)(?<V1>)(?<V2>[\w\d\.+=\/]+)/"$+{V1}$+{V2}"/g
命名替换和分支重置这两个概念可以合并
如果交替包含超过 1 个捕获组。
下面的示例使用捕获组编号。
理论是你将 dummy 个捕获组放在
的每个交替中
"pad" 分支等于单个交替中的最大组数。
确实,必须这样做以避免 Perl 正则表达式中可能导致崩溃的错误。
(?| # Branch Reset
# ------ Br 1 --------
( ) # (1)
( \d{4} ) # (2)
ABC294
( [a-f]+ ) # (3)
|
# ------ Br 2 --------
( :: ) # (1)
( \d+ ) # (2)
ABC555
( ) # (3)
|
# ------ Br 3 --------
( == ) # (1)
( ) # (2)
ABC18888
( ) # (3)
)
s/(?|()(\d{4})ABC294([a-f]+)|(::)(\d+)ABC555()|(==)()ABC18888())/""/g
您可以尝试使用 Cpanel::JSON::XS's relaxed mode, or JSONY,解析几乎-JSON,然后使用 Cpanel::JSON::XS 写出常规 JSON。根据您的输入数据到底出了什么问题,一个或另一个可能会更好地理解它。
use strict;
use warnings;
use Cpanel::JSON::XS 'encode_json';
# JSON is normally UTF-8 encoded; if you're reading it from a file, you will likely need to decode it from UTF-8
my $string = q<{foo: 1,bar:'baz',}>;
my $data = Cpanel::JSON::XS->new->relaxed->decode($string);
my $json = encode_json $data;
print "$json\n";
use JSONY;
my $data = JSONY->new->load($string);
my $json = encode_json $data;
print "$json\n";