用PHP解析Javascript文件以提取其中定义的数组的最佳方法

4
我有一个JavaScript文件,它是从一个遗留应用程序自动生成的,其中定义了一个巨大的数组(以及一些其他函数和内容)。这个JavaScript文件对内容进行搜索,但随着时间的推移,它已经增长到超过2Mb,听起来可能不多,但每次使用此特定Web应用程序进行搜索时都需要下载它。不用说,性能非常糟糕。我想找到一种最小的方法来包装js,以便不再在客户端调用js,而是调用我的新php脚本来对内容进行搜索。
生成的JS文件的布局每次生成时都相同,因此我可以编写一堆特定的修剪和分割代码,但我认为正则表达式可能是更好的选择,但老实说我不确定,所以我想问问你们可爱的人。
示例源代码:
Page[0]=new Array("Some text1","More text1","Final Text1","abc.html");
Page[1]=new Array("Some text2","More text2","xyz.html");

正如您所看到的,每个数组行中至少有一个条目,最后一个条目是要搜索的文件名。

无论如何,问题是,是否使用正则表达式最佳(如果是,则一些建议的模式将非常好)。或者我应该使用split等方法进行拆分。

干杯


我希望...那是我列表上的下一个挑战...有时候,把一个包装器放在糟糕的代码周围会更容易,一旦它被使用,再处理重写代码的政治问题...政治,喜悦... - Bill Burroughs
5个回答

4
你正在寻找类似这样的东西。请注意,我将.js文件作为本地文件使用,因此我使用了file()将其加载到数组中。对于你实际的脚本,如果你的php无法本地访问.js文件,你可能需要使用file_get_contents()
<?php
$lines = file('test.js');

    $pages = array();

    foreach($lines as $line) {
        if(strpos($line, 'new Array') != false) {

            preg_match('/Page\[\d\]\s?\=\s?new Array\((\"(.*)",?\s?\n?)+\);/', $line, $matches);


            $values = preg_split('/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/', $matches[1]);

            $currNo = count($pages);
            $pages[$currNo] = array();

            for($i = 0; $i < count($values); $i++) {
                array_push($pages[$currNo], trim($values[$i], '"'));
            }


        }
    }

    var_dump($pages);

对于您的示例,结果将如下所示:
array(2) {
  [0]=>
  array(4) {
    [0]=>
    string(10) "Some text1"
    [1]=>
    string(10) "More text1"
    [2]=>
    string(11) "Final Text1"
    [3]=>
    string(8) "abc.html"
  }
  [1]=>
  array(3) {
    [0]=>
    string(10) "Some text2"
    [1]=>
    string(10) "More text2"
    [2]=>
    string(8) "xyz.html"
  }
}

尽情享受吧!


看起来差不多就是这样,如果这个方法奏效的话,我会尽快告诉你。 - Bill Burroughs
没错,成功了!我只需要做出一点改变,就是在 \d\ 后面加上一个 + ,以允许方括号中的值为 1 或多个数字。因此,第一个正则表达式现在是:preg_match('/Page\[\d+\]\s?\=\s?new Array\((\"(.*)",?\s?\n?)+\);/', $line, $matches);非常感谢你的帮助,Bogdan! :) - Bill Burroughs
糟糕,忘记添加注释了 - 我必须进行了一些微小的调整,但是这个完美地起作用了,感谢Bogdan! :) - Bill Burroughs

1

使用基于PHP的JavaScript解释器(例如J4P5)怎么样?
我自己从未尝试过,但这个想法是在服务器端运行js文件并从内存中读取该数组。这样可以避免正则表达式和让用户下载js文件。


0

尝试

/Page\[\d\]=new Array\((.*)\);/simU

示例:

$js = <<< JS
Page[0]=new Array("Some text1","More text1","Final Text1","abc.html");
Page[1]=new Array("Some text2","More text2","xyz.html");
JS;
preg_match_all('/Page\[\d\]=new Array\((.*)\);/simU', $js, $matches);
print_r(array_map('str_getcsv', $matches[1]));

输出结果(在线演示):

Array
(
[0] => Array
    (
        [0] => Some text1
        [1] => More text1
        [2] => Final Text1
        [3] => abc.html
    )

[1] => Array
    (
        [0] => Some text2
        [1] => More text2
        [2] => xyz.html
    )
)

0

我的看法是将JS转换为PHP并使用eval()进行评估。(GASP

只是开个玩笑。不过,您可以将其转换为PHP并进行标记化。 我认为在正则表达式变得过于复杂的情况下,这可能更好。

我以为我有正确的解决方案,但显然它将PHP转换为JS(嗯;P) 我会在这里尝试自己的小尝试...

$js='Page[0]=new Array("Some text1","More text1","Final Text1","abc.html"); '.
    'Page[1]=new Array("Some text2","More text2","xyz.html");';

// Convert JS variable names to PHP (this seems pretty consistent in your app)
$php='<?php '.str_replace('Page[','$Page[',$js);
//      '---PHP tag, tells tokenizer this is PHP code

// Parse the PHP-JS thingy
token_get_all($php);

0

使用AJAX完全避免解析JS。使用AJAX,您可以轻松地将这些数组发送到PHP文件,处理内容并再次将结果返回给JavaScript。


这意味着用户首先下载2MB,然后通过Ajax发送相同的2MB。听起来不太明智,是吧? - Gordon
@Gordon:我可能误解了问题,但用 PHP 解析 JavaScript 文件甚至更不好的想法...JSON + AJAX 可能是实现它的最佳方式。 - Shoe
1
抱歉,Charlie,我和Gordon在一起,我们的想法是避免下载JS文件 - 我们将从前端使用一些非常简单的AJAX调用PHP脚本... - Bill Burroughs
如果它已经是JSON格式,我会非常高兴,但不幸的是它不是 :( 它的格式如上所示,在数组之前和之后还有一些额外的文本。我正在努力处理这个正则表达式,但目前我每年只需要处理一次正则表达式,所以我对此感到害怕... - Bill Burroughs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接