1

我需要从网站上获取不同类型的信息。知道格式是这样的(都在一行上):

"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 在第一次到达“state”后会跳过字符串)我的问题是这是怎么发生的?我该如何解决?

4

2 回答 2

3

对我来说,这看起来很像JSON —— 确实是这样。找出来,您可以使用以下方法将整个字符串转换为带有字段namecontactlocation等的散列:

#!/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}; 

我不得不添加一个{between "location":and "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)的常用数据交换格式,尤其是在线。

于 2012-05-19T14:37:17.647 回答
0

对于这种特殊情况,JSON 解析器绝对是解决它的正确方法 - 您只描述了尝试使用正则表达式解析 JSON 的众多陷阱之一。

但是,要回答有关正则表达式的实际问题:

当您在标量上下文中使用带有/g修饰符的正则表达式时(您的使用是在标量上下文中,因为结果被分配给标量),它只处理第一个匹配项,然后停止并等待您是否会调用相同的正则表达式再次在同一字符串上以获取下一个匹配项。因此,正则表达式 with/g通常在标量上下文中使用 awhile而不是 a 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正则表达式修饰符。

于 2012-05-20T11:33:58.907 回答