首页
学习
活动
专区
圈层
工具
发布

Regex提取
EN

Stack Overflow用户
提问于 2012-05-25 15:16:53
回答 6查看 134关注 0票数 1

我一直在试着从绳子里提取东西。我拿到了折叠式绳子:

*, bob, DATE('gdfgfd', 'Fdsfds', ('fdsfdfsd')), george

我想用逗号提取and (),它应该给出如下内容:

  • *
  • bob
  • DATE('gdfgfd','Fdsfds',('fdsfdfsd'))
  • george

我试着用爆炸的方法,但它甚至在里面也会爆炸.逻辑指的是函数。

因此,我已经这样做了:[^(,\s]+|\([^)]+\),但是即使在括号中找到逗号,它也会给出切分。

有人知道怎么做我的意思吗?

谢谢

编辑:

好的,非常清楚和直接。

我拿到了这个:SELECT MyField, Field2, Blabla, Function(param), etc FROM table Blabla

我已经得到了字符串MyField, Field2, Blabla, Function(param), etc,因为查询是由多个函数类(如$DB->Select('MyField, Field2, Blabla, Function(param), etc'); )完成的,但是现在我想解析逗号之间的所有内容,因此MyField, Field2, Blabla, Function(param), etc变成如下所示:

  • MyField
  • Field2
  • Blabla
  • Function(param)
  • etc
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-05-25 15:55:08

以下是我所做的,不支持多字节字符的内容:

编辑:添加字符串感知

代码语言:javascript
复制
<?php


$stack = array();
$stuff = array();

$escaping = false;
$input = "*, bob, [], DATE('g()d\\'f,gfd', ('Fd()sf)ds'), ('fdsfd\"\"()fsd')), ',(),() (,,'";
$len = strlen( $input );
$i = 0;
$curstr = "";
$char;

while( $i < $len ) {
    $char = $input[$i++];

    if( $escaping ) {
        $curstr .= $char;
        $escaping = false;
        continue;
    }

    switch( $char ) {

        case "\\":
            $escaping = true;
            break;

        case '"':
            $top = end( $stack );
            if( $top === '"' ) {
                array_pop( $stack );
            }
            else if( $top !== "'" ){
                $stack[] = '"';
            }

            $curstr .= $char;
            break;

        case "'":
            $top = end( $stack );
            if( $top === "'" ) {
                array_pop( $stack );
            }
            else if( $top !== '"' ) {
                $stack[] = "'";
            }

            $curstr .= $char;           
            break;

        case ",":
            if( count( $stack ) ) {
                $curstr .= $char;
            }
            else {
                $stuff[] = trim($curstr);
                $curstr = "";
            }
            break;

        case "(":
            $top = end( $stack );
            if( $top !== "'" && $top !== '"' ) {
                $stack[] = "(";                   
            }

            $curstr .= $char;
            break;

        case ")":
            $top = end( $stack );

            if( $top !== "'" && $top !== '"' ) {
                if( end($stack) !== "(" ) {
                    die( "Unbalanced parentheses" );
                }
                array_pop( $stack );
            }

            $curstr .= $char;


            break;

        default:
            $curstr .= $char;
            break;

    }
}

if( count( $stack ) ) {
    die( "Unbalanced ".end($stack) );
}

$stuff[] = trim( $curstr );

print_r( $stuff );

/*
    Array
(
    [0] => *
    [1] => bob
    [2] => []
    [3] => DATE('g()d'f,gfd', ('Fd()sf)ds'), ('fdsfd""()fsd'))
    [4] => ',(),() (,,'
)

*/
票数 2
EN

Stack Overflow用户

发布于 2012-05-25 15:50:48

将此作为答案发布,因为它可能比其他任何东西都要好:

http://code.google.com/p/php-sql-parser/

使用该项目解析SQL语句。结果返回为数组,包括SELECTFROM之间的位作为单独的元素,就像您想要的那样。这将比您使用的任何正则表达式解决方案工作得更好。

票数 4
EN

Stack Overflow用户

发布于 2012-05-25 15:31:15

您在注释中指出,您准备使用递归,因为您有嵌套列表。但是,正则表达式不能执行递归。这是因为regex不能无限期地“计数”任何事情。因为它没有计算开/闭括号的方法,所以它无法知道其中有多少个级别,也不知道它必须达到多少个级别。

您可以编写非常复杂的regex来处理N个深度级别(请参阅anubhava's answer),但一旦遇到具有N+1深度级别的表达式,正则表达式就会失败。这就是为什么我们使用编程语言来解析不规则语言的原因,因为它们可以计算递归(参见diolemo's answer)。在这个递归中,我们可以使用小的正则表达式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10757028

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档