【问题标题】:What perl regular expression will correctly match a javascript associative array?什么 perl 正则表达式将正确匹配 javascript 关联数组?
【发布时间】:2016-01-02 18:40:20
【问题描述】:

我有一些需要用 Perl 解析的 Javascript 代码:

var materials ={
    foo: "bar",
    bar: "baz",
    baz: "foo"
},

我将这个 Javascript 变量作为一个字符串,我想匹配关联数组的主体,以便我可以使用 Perl 使用 parse_json() 将其解析为 JSON。我无法弄清楚我的正则表达式做错了什么:

my ($json_str) = $js_code =~ m/var\smaterials\s=\s+({.+}),/i;

$json_str 最终未初始化。

【问题讨论】:

  • 您可能只是以不同的方式看待它。现在您正在尝试匹配字符串的 json 部分。修复您的正则表达式将是微不足道的(允许\s* 而不是要求\s+)。但是,JSON 可能比此示例更复杂。删除不需要的部分可能更容易:s/^[^{]+//。这将删除第一个 { 之前的所有内容。
  • 不过,您实际上想做什么? JSON.stringify(materials) 将为您提供真正的 JSON,让一切变得更容易。

标签: javascript json regex perl


【解决方案1】:
my ($json_str) = $js_code =~ m/var\smaterials\s=\s*({[\s\S]+?}),/i;

                                                      ^^^^

问题是.默认不匹配\n。所以要么使用[\s\S],要么使用(?s)DOTALL标志。

查看演示。

https://regex101.com/r/cJ6zQ3/7

https://regex101.com/r/cJ6zQ3/8

【讨论】:

  • 为什么[\s\S]+ 也不匹配'}'? (以及直到字符串结尾的所有其余部分)它不需要惰性修饰符'?' 来工作吗?像这样[\s\S]+?
  • @GsusRecovery 这与你的答案有同样的问题。你的假设是错误的。它将匹配 } 但随后它会回溯,因为 re 也必须匹配 }。至 [\s\S]将回溯离开} 以匹配}。与, 相同。仅当有多个} 时才需要?,因为它将匹配到最后一个}
【解决方案2】:

如果您可以引用 JSON 对象的键(如下例所示),您可以尝试 JSON::Decode::Regexp,该模块包含一个可用于匹配 JSON 的正则表达式。作为奖励,您可以将 JSON 对象加载为 Perl 哈希。示例代码:

use Data::Dump;
use JSON::Decode::Regexp;

my $json_code = <<'_';
var materials ={
    "foo": "bar",
    "bar": "baz",
    "baz": "foo"
},
_

if ($json_code =~ /(\{.+)/s) {
    local $_ = $1;
    local $^R;
    eval { /\A$JSON::Decode::Regexp::FROM_JSON/ } or die "No match";
    die "No match: $@" if $@;
    print "Match: "; dd $_;
}

将打印:

Match: { bar => "baz", baz => "foo", foo => "bar" }

【讨论】:

    【解决方案3】:

    如果有多个元素,使用像 [^}]+ 这样的排除组也可以正常工作:

    #!/usr/bin/env perl
    
    my $js_code = <<'__END__';
    var previousOne =  {
        pFoo: "pBar",
        pBar: "pBaz",
        pBaz: "pFoo"
    },
    var materials ={
        foo: "bar",
        bar: "baz",
        baz: "foo"
    },
    var anotherOne = {
       aFoo: "aBar",
       aBar: "aBaz",
       aBaz: "aFoo"
    }
    __END__
    
    my ($json_str) = $js_code =~ m/\s*var\s+materials\s*=\s*({[^}]+}),?/;
    print "json_str = ${json_str}\n";
    

    我已经放宽了一些空白限制。可以在线测试和编辑here

    【讨论】:

    • 为什么要投反对票?这是一个真正的问题。我已经测试过了(每个人都可以在答案中执行相同的 perl 脚本......)
    • 感谢您为我指明了正确的方向:我已经用不回溯的贪婪 possessive 行为(如[\s\S]++)折叠了带有回溯行为的默认贪婪行为全部。我已经删除了错误的假设,但保留了代码,因为它可以工作。
    【解决方案4】:

    等号和大括号之间没有空格,但该模式至少需要一个空格。删除\s+ 或将其更改为\s*

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
    • @WesFoster 这怎么不是答案?这是解决问题的一种尝试,据我所知,这是一个正确的尝试。你能在这里详细说明你的推理吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多