我需要从网站上获取不同类型的信息。它知道格式是这样的(所有在一行):
"name":"BLAHBLAH","contact":{"phone":"12345","twitter":"BLAHBLAH"},
"location": "address":"NOTTELLING","lat":10,"lng":10,"postalCode":"1234",
"city":"BLAH","state":"BLAH","country":"BLAH"},
"categories":[{"id":"BLAH","name":"BLAH"}]
其中一些配置文件会丢失一个或两个块,例如没有名称,没有城市等。 我尝试了这样的代码:
#get name
$content =~ m!","name":"(.*?)","contact":!igs;
say ("name:", $1) unless ($1 eq '');
#get street
if ($content =~ m!\},"location":\{"address":"(.*?)","lat":!igs)
{say ("street:", $1) unless ($1 eq '');}
#get city
if ($content =~ m!,"city":"(.*?)","state":!igs)
{say ("city:", $1) unless ($1 eq '');}
#get state
if ($content =~ m!,"state":"(.*?)","country":!igs)
{say ("state:", $1) unless ($1 eq '');}
然后我意识到当我使用重复模式时(例如
"city":"(.*?)","state":!igs
和
"state":"(.*?)","country":!igs)
结果不准确。 (我猜perl第一次到达后会跳过字符串,#34;状态")我的问题是这是怎么发生的?以及如何解决它?
答案 0 :(得分:3)
对我来说,这看起来很像 JSON - 它就是这样。找出并使用以下字段将整个字符串转换为包含字段name
,contact
,location
等的哈希值。
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
use JSON::XS;
use YAML::XS;
my $json = <<HERE;
{
"name":"BLAHBLAH","contact":{"phone":"12345","twitter":"BLAHBLAH"},
"location": {"address":"NOTTELLING","lat":10,"lng":10,"postalCode":"1234",
"city":"BLAH","state":"BLAH","country":"BLAH"},
"categories":[{"id":"BLAH","name":"BLAH"}]
}
HERE
print $json;
my $hash_ref = decode_json($json);
print Dump $hash_ref->{location};
我必须在{
和"location":
之间添加"address":
,猜测这是你的最终错字。无论如何,那么输出是:
{
"name":"BLAHBLAH","contact":{"phone":"12345","twitter":"BLAHBLAH"},
"location": {"address":"NOTTELLING","lat":10,"lng":10,"postalCode":"1234",
"city":"BLAH","state":"BLAH","country":"BLAH"},
"categories":[{"id":"BLAH","name":"BLAH"}]
}
---
address: NOTTELLING
city: BLAH
country: BLAH
lat: 10
lng: 10
postalCode: '1234'
state: BLAH
为简洁起见,我使用了YAML::XS
;你不需要那个。如果您还没有看到这一点,请考虑:
print $hash_ref->{location}->{state};
给你BLAH
。
JSON是“javascript对象表示法”,它是OO语言(如perl)的常用数据交换格式,尤其是在线。
答案 1 :(得分:0)
对于这种特殊情况,JSON解析器绝对是正确的方法 - 你只描述了尝试用正则表达式解析JSON时的众多陷阱中的一个。
回答有关正则表达式的实际问题:
当你在标量上下文中使用带有/g
修饰符的正则表达式时(你的使用是在标量上下文中,因为结果被分配给标量),它只处理第一个匹配,然后停止并等待查看如果你在相同的字符串上再次调用相同的正则表达式以获得下一个匹配。因此,带有/g
的正则表达式通常在标量上下文中使用while
而不是if
:
$ perl -E 'while ("This is an example string." =~ /\b(\w{2,6})\b/g) { say $1 }'
This
is
an
string
使用带有/g
修饰符的正则表达式的另一种方法是将其放在数组上下文中(通过将结果赋值给数组)。在这种情况下,它将立即返回所有匹配的列表:
$ perl -E '@matches = "This is an example string." =~ /\b(\w{2,6})\b/g; say join ",", @matches;'
This,is,an,string
如果你没有做这两件事之一(在标量上下文中循环结果或在数组上下文中使用完整的匹配列表),你可能不想使用/g
正则表达式修饰符