Regexp,在字符串之间匹配字符串,然后在匹配中的字符串之间匹配字符串


regexp, match string between strings and then between strings in that match

我想在这个结构中解析选项来上传方法:

<script>
$(function() {
  $("#file_upload_1").uploadify({
    uploader : '/uploadify/uploadify.php',
  });
});
</script>

我能够提取脚本标签之间的一切使用:

$matches = array(); reg_match('/.*<script>(.*)<script>/s', $s, $matches);

却不知道如何继续前进。我需要删除$matches[1]中的所有内容,在"uploadify({"(因为它是关键字)之前,以及第一次出现"}"之后;"

您似乎在php提供preg_match的regex函数中错过了p。尽管如此,您可以使用以下regex来匹配上传方法;

preg_match('/<script>.*?(uploadify'({.*?}');).*<'/script>/s', $s, $matches);

您的模式中似乎缺少一个转义斜杠:

/.*<script>(.*)<'/script>/s

更改分隔符会更容易,但是:

~.*<script>(.*)</script>~s

请注意,这将为您获得输入中的最后一个<script>对(.*将尽可能多地消耗,将两个标签尽可能地向后推)。如果这是你想要的,很公平。

在任何情况下,最好使用DOM解析器来获取script标签的内容。它更健壮,更可读,等等。以下是使用PHP完成此操作的选项概述。

现在是你真正的问题。同样,JavaScript或JSON解析器可能会有所帮助,但使用正则表达式时,您可以使用非贪婪重复,以确保匹配只到第一个});:

/uplodify[(][{](.*?)[}][)];/s

这种方法的主要问题是});可能出现在字符串或注释中,甚至可能出现在嵌套匿名函数的末尾。尽管PCRE在正则表达式中提供了递归(?R)结构,但试图用它来解析JavaScript肯定会让你的大脑(以及将来试图理解代码的任何人的大脑)融化。这就是为什么(对于一个健壮的解决方案)应该使用某种JavaScript解析器来解决这个问题。

你甚至可能更好,只是寻找uploadify,然后通过字符串的其余字符逐个字符,计算不同类型的嵌套级别,JavaScript有,以确保你正在寻找正确的});

因为您确实需要选项,一个JS对象,这里有一个死星大小的解决方案来本地解析这些东西。这里的想法是提取你想要的部分,在JS中的{}JSON对象之间,然后用PHP的json_decode将其评估为可用的结构。在这段代码中,我将HTML片段存储到$variable0中。

// expression broken down for readability
$frag = array(
    "/<script>",
    ".*?",             # whitespace
    "uploadify'(",
        "(.*?)",       # our desired match
    "');",             # closest )
    "(.*)",            # more whitespace we don't want
    "<'/script>/s"
);
// flatten expression into match string
$expr = implode("", $frag );

此时,$expr = /<script>.*?uploadify'((.*?)');(.*)<'/script>/s

$m = preg_match( $expr, $variable0, $r );

现在$r应该是一个数组,其中$r[1]包含"{…}"片段。这可以用json_decode来求值,但是,json_decode使用的字符串格式是错误的。首先,关键字必须括在引号(即:uploader:"应该是'uploader':")在javascript。字面上,$r[1]看起来像这样:

{
    uploader : '/uploadify/uploadify.php',
  }

另一个人想出了一个清理函数,我们可以在这里应用。

// fix thanks to http://stackoverflow.com/a/14075951/415324
function fix_json( $a ) {
    $a = preg_replace('/(,|'{)[ 't'n]*('w+)[ ]*:[ ]*/','$1"$2":',$a);
    $a = preg_replace(
      '/":''?([^'[']'{'}]*?)''?[ 'n't]*(,"|'}$|']$|'}']|']'}|'}|'])/','":"$1"$2',
    $a);
    return( $a );
}
// $r[1] will contain innards of uploadify(), which is JSON
$json = fix_json( $r[1] );

这将$json转换为PHP可以本地解析的内容。$json现在看起来像:

{"uploader":"/uploadify/uploadify.php',"}

注意后面有一个逗号。这是您正在提取的原始HTML中的javascript错误,需要在站点上进行修复。

$options = json_decode( $json );

现在,我们有了一个可以在PHP中使用的对象

var_dump( $options );
object(stdClass)#2 (1) {
  ["uploader"]=>
  string(24) "/uploadify/uploadify.php"
}

因此,您可以使用echo $options->uploader;

轻松访问遇到的任何其他选项。

注意:原始HTML有一个问题——它包含一个逗号,在某些浏览器中会破坏javascript解析。我认为FireFox会给它一些放松,但IE肯定不会。要修复JS,请删除options对象后面的逗号:

$("#file_upload_1").uploadify({
  uploader : '/uploadify/uploadify.php'
});