0

I need to open a JS file from PHP, to find a json var in this file, and convert it to a php array.

Right now I can't figure out which regex to use.

// get the js file
$file = file_get_contents ("http://pve.proxmox.com/pve2-api-doc/apidoc.js");

// extract the json content of var pveapi
if ( preg_match ( "#pveapi = ({[^}]*})#", $file, $infoJson ) ) {
    $arrJson = json_decode ( $infoJson [1], true );
}

// shows nothing so far :((
print_r($arrJson);

I have found few examples to do that, but none would work for me. Anyone with decent skills in regex could help me please ?

Ben

edit: added a part of the js file :

var pveapi = [
   {
      "info" : {
         "GET" : {
            "parameters" : {
               "additionalProperties" : 0
            },
            "permissions" : {
               "user" : "all"
            },
            "returns" : {
               "type" : "array",
               "items" : {
                  "type" : "object",
                  "properties" : {}
               },
               "links" : [
                  {
                     "rel" : "child",
                     "href" : "{name}"
                  }
               ]
            },
            "name" : "index",
            "method" : "GET",
            "description" : "Cluster index."
         }
      }
    }
];

Ext.onReady(function() { ... }
Asterix34
  • 3
  • 1
  • 4
  • try `"#pveapi\s*=\s*({[^}]*})#"` – Avinash Raj Feb 25 '15 at 13:02
  • thanks for the answer, i tried but it's still the same, not matching. – Asterix34 Feb 25 '15 at 13:13
  • "/pveapi\s*\=\s*([^Ext\.onReady]*)/" – hanshenrik Feb 25 '15 at 13:31
  • if you know that the pveapi you need is the first instance of var pveapi = in your javascript, AND you know that the pveapi does not contain the string Ext.onReady , AND you know that right after the pveapi, there's a Ext.onReady , this should work ... unfortunately i think you'll need a full-fledged javascript interpreter to grab the code reliably – hanshenrik Feb 25 '15 at 13:32

2 Answers2

3

In this case, the end can be found by matching a semicolon at the end of a line:

if (preg_match('/^var pveapi = (.*?);$/ms', $js, $matches)) {
    $data = json_decode($matches[1]);
    print_r($data);
}
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
0

Per default the RegEx engine operates greedily on individual lines, so you'd have to tell it to do the opposite – the RegEx you seem to be looking for would be

#\spveapi\s*=\s*(.*?);\s*$#s

What it does is:

  • #
    Start the expression
  • \s
    Make sure the variable name is preceded by whitespace, so it's not part of a different variable name
  • pveapi
    Find the variable
  • \s*=\s*
    Make sure there's an equal sign with optional whitespace around it
  • (.*?);\s*$
    Get as few characters as possible before finding a semicolon – i.e. all characters until the first semicolon that is follow only by optional whitespace and a line ending
  • #ms
    End the expression and tell it to let . match line endings too and match $ to the ending of each line
Flygenring
  • 3,818
  • 1
  • 32
  • 39
  • thanks for the answer and the details, there is little typo in your answer in the last part, you meant #ms instead of #s. – Asterix34 Feb 25 '15 at 14:01
  • Yeah, I saw that my answer could be more complete, so edited it to add the whitespace and line ending to the 'stop clause' and the `m` to use it ;) – Flygenring Feb 25 '15 at 14:09