【问题标题】:How to multiple search on the same string using regular expression in perl?如何在perl中使用正则表达式对同一字符串进行多次搜索?
【发布时间】:2012-05-26 19:25:14
【问题描述】:

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

"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”后会跳过字符串)我的问题是这是怎么发生的?以及如何解决?

【问题讨论】:

  • 看起来像 JSON。您是否尝试过使用 JSON 解析器?
  • 不,你能提供更多细节或教程吗?我对一切都很陌生
  • 请使用谷歌。 JSON 是当今非常常见的格式,您会发现很多关于在 Perl 中使用它的信息。

标签: regex json perl search


【解决方案1】:

在我看来,这很像 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}; 

我不得不在"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)的常用数据交换格式,尤其是在线。

【讨论】:

  • 很好的解决方案和很好的解释。这对像我这样的新手很有帮助,谢谢。
【解决方案2】:

对于这种特殊情况,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 正则表达式修饰符。

【讨论】:

  • 好吧,那么有什么办法可以在使用 /g 后重置搜索位置?例如,我使用 /g 在一个内容中获得了文本“abc”的所有匹配项。那么如何在同一内容中搜索“defghi”的所有匹配项?
  • 再做一次。匹配失败后(例如,因为您点击了字符串的末尾),它会重置为字符串的开头。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-08
  • 2010-12-09
  • 2013-08-19
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
相关资源
最近更新 更多