我有一个由','分隔的键值对,如下所示。我只需要提取值,无论它是否存在。
Category=, userAgent=Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko, referringURL=https://www.localhost.com/account/pay?link=credit_card, criteria=InFormCriteria(cc='MZ',tend=123,cd='parts')
我使用了以下代码,
while(<FH>){
while($_=~m/([^=]+)=([^\s]+,?)/g){
print $1." ";
}
print "\n";
}
我得到以下输出:
, Mozilla/5.0 https://www.localhost.com/account/pay?link=credit_card, InFormCriteria(cc='MZ',tend=123,cd='parts')
但是,我需要得到:
""@@Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko@@https://www.localhost.com/account/pay?link=credit_card@@InFormCriteria(cc='MZ',tend=123,cd='parts')
我做错了什么?
答案 0 :(得分:1)
它比听起来更烦人,因为你的字符串使用不一致的分隔符。因此,很难用RE解析,并且总是不可靠。
存在这样做的模块 - 正如Wintermute所提到的,HTTP::BrowserDetect
是为解析这种特殊类型的字符串而构建的。
如果你真的开始这么做的话 - 简单的&#39;由于在括号中嵌套了元素,split_on_delimiter方法无法工作。所以我建议 - 用正则表达式挑选密钥(因为它们总是一个字,然后是=
)。
然后,创建一堆&#39; sub&#39;正则表达式,解析它。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $string =
q{Category=, userAgent=Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko, referringURL=https://www.localhost.com/account/pay?link=credit_card, criteria=InFormCriteria(cc='MZ',tend=123,cd='parts')};
my @keys = ( $string =~ m/(?:^|\s)(\w+)=/g );
my %parsed_thing;
for my $index ( 0 .. $#keys ) {
my $regex =
$keys[$index]
. '=(.*?)[, ]*'
. ( defined $keys[ $index + 1 ] ? $keys[ $index + 1 ] : '$' );
print "Using a RE of: ", $regex, "\n";
my ($value) = ( $string =~ m/$regex/ );
print "\tGot: $keys[$index] => $value\n";
$parsed_thing{ $keys[$index] } = $value;
}
print join( '@@', values %parsed_thing ),"\n";
#or
print join( '@@', @parsed_thing{@keys} ),"\n";
答案 1 :(得分:1)
您的实际分隔符看起来更像,
(逗号后跟空格)。如果key = value对的值不包含相同的分隔符,则可以使用gawk:
gawk '{sub(/^\w+=/, ""); gsub( /, \w+=/, "@@"); print}'
删除第一个字段中的key = part,然后将其他字段转换为@@
。您的示例数据输出对我来说是这样的:
@@Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko@@https://www.localhost.com/account/pay?link=credit_card@@InFormCriteria(cc='MZ'@@123@@'parts')
如果您确实需要将空值表示为""
,则可以在脚本中使用常规gawk / awk:
#!/usr/bin/awk -f
BEGIN {FS=", "; OFS="@@"}
{
for(i=1; i<=NF; i++) {
val = substr( $i, index( $i, "=" )+1 )
if( val=="" ) val="\"\""
printf "%s%s", val, (i<NF?OFS:"\n")
}
}
或者,你也可以将这些字段分成或者gsub到""
。该脚本为我输出以下内容:
""@@Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko@@https://www.localhost.com/account/pay?link=credit_card@@InFormCriteria(cc='MZ',tend=123,cd='parts')
这些解决方案都假设每个字段都是key = value,并且没有值包含,
(逗号后跟空格)。如果后者不成立,那么您可能希望将日志记录定界符(如果可以)更改为更明确的内容。或者,如果您可以确定,
在某个值中的不同情况(例如在平衡数据之间),则可以在解析主键=值对之前更改这些情况。