2

我的 PHP 代码如下所示:

$input = "City.name = '纽约'";
$literal_pattern = '/\'.[^\']*\'/';
preg_match($literal_pattern, $input, $token);
回声$令牌[0];// 打印“纽约”

我的正则表达式需要使用转义的单引号来获取文字,例如:

$input = "City.name = '新\'约克'";
$literal_pattern = ?????????????;
preg_match($literal_pattern, $input, $token);
回声$令牌[0];// 应该打印 'New \' York'

$literal_pattern 的规则是什么?

4

4 回答 4

6

没有这个条件,简单...

/('[^']*')/

...当然就足够了:匹配所有“单引号,后跟任意数量的非单引号符号,再后跟单引号”的序列。

但是因为我们需要在这里为两件事做好准备——“正常”和“逃逸”。所以我们应该为我们的模式添加一些香料:

/('[^'\\]*(?:\\.[^'\\]*)*')/

它可能看起来很奇怪(确实如此),但实际上也很简单:匹配...的序列

  • 单引号...
  • ...后跟零个或多个“正常”字符(不是'or \),
  • ...后跟(“转义”符号,然后是零个或多个“正常”符号)的子表达式,重复 0 次或更多次...
  • 后跟一个单引号。

例子:

$input   = "City.name = 'New \\' York (And Some Backslash Fun)\\\\'\\'"; 
# ...as \' in any string literal will be parsed as a _single_ quote

$pattern = "/('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')/";
# ... a choice: escape either slashes or single quotes; I choose the former

preg_match($pattern, $input, $token);
echo $token[0]; // 'New \' York (And Some Backslash Fun)\\'
于 2012-11-06T23:55:25.167 回答
2

这是您要查找的正则表达式:/\'(\\.|[^\'\\])*\'/

在 PHP 中,这看起来像$literal_pattern = '/(\'(?:\\.|[^\'\\])*\')/';

于 2012-11-07T00:00:22.807 回答
1

正则表达式是自动贪婪的,因此它会使用文字捕获尽可能多的数据。因此,如果您识别“ 's 之间的所有内容”,它将捕获 first 和 last 之间的任何内容'

因此,您可以安全地执行此操作:

$literal_pattern = "#('.*')#";

示例:http: //ideone.com/gI5bXs

注意:正如@m.buettner 所指出的,这种方法只有'在您的输入中有一个 -encased 字符串时才有效。

于 2012-11-06T23:56:38.573 回答
0

您可以使用否定的后向匹配。http://www.regular-expressions.info/lookaround.html

(?<!a)b匹配前面没有“a”的“b”,使用否定的lookbehind

唯一的事情是我很确定 PHP 正则表达式不支持它。如果它们受到支持,正则表达式将如下所示:

/(?<!\\)'(.*?)(?<!\\)'/

我的建议是使用一个简单的解析器。这是我刚想出来的东西(显然是用伪代码):不保证它的逻辑可以满足您的目的,但实际上构建自己并不太难。

let inString = false
let escaping = false
let match = ''    
for each letter in string
    if letter == "\\" and not escaping
        escaping = true
    else
        if letter == "'" and not escaping
            inString = not inString
        else if inString
            match += letter
        escaping = false
return match
于 2012-11-07T00:15:38.840 回答