PHP复杂的字符串解析

时间:2016-03-07 01:07:32

标签: php regex parsing

这可以用正则表达式完成,但我不知道。我想要完成的是能够解析具有给定分隔符的字符串,但是当它看到一组括号时,它会以不同方式解析。由于我是一个视觉学习,让我向您展示我试图实现的目标。 (PS这是从网址解析的)

给出字符串输入:

String1,String2(data1,data2,data3),String3,String4

如何将此字符串“转换”为此数组:

{
    "String1": "String1",
    "String2": [
        "data1",
        "data2",
        "data3"
    ],
    "String3": "String3",
    "String4": "String4
}

格式化不一定非常严格,因为我只是想为我的项目制作一个简单的API。

显然像

这样的事情

array explode ( string $delimiter , string $string [, int $limit = PHP_INT_MAX ] )

无效,因为括号内也有逗号。我曾尝试手动解析每次查看每个角色,但我担心性能,但实际上它并没有真正起作用。我已经粘贴了我的尝试的主旨。

https://gist.github.com/Fudge0952/24cb4e6a4ec288a4c492

3 个答案:

答案 0 :(得分:1)

虽然您可以尝试在逗号上拆分初始字符串并忽略第一次拆分的括号中的任何内容,但这必然会假设这些字符串值实际上是什么(可能需要转义/取消转义值取决于这些字符串的含义包含)。

如果您可以控制数据格式,那么从JSON开始会好得多。它定义明确且得到很好的支持。

答案 1 :(得分:1)

您可以构建一个特殊的解析器(主要是未经测试的):

<?php
$p = '!
    [^,\(\)]+  # token: String
    |,         # token: comma
    |\(        # token: open
    |\)        # token: close
!x';
$input = 'String1,String2(data1,data2,data3,data4(a,b,c)),String3,String4';

preg_match_all($p, $input, $m);
// using a norewinditerator, so we can use nested foreach-loops on the same iterator
$it = new NoRewindIterator(
    new ArrayIterator($m[0])
);

var_export( foo( $it ) );

function foo($tokens, $level=0) {
    $result = [];
    $current = null;
    foreach( $tokens as $t ) {
        switch($t) {
            case ')':
                break; // foreach loop
            case '(':
                if ( is_null($current) ) {
                    throw new Exception('moo');
                }
                $tokens->next();
                $result[$current] = foo($tokens, $level+1);
                $current = null;
                break;
            case ',':
                if ( !is_null($current) ) {
                    $result[] = $current;
                    $current = null;
                }
                break;
            default:
                $current = $t;
                break;
        }   
    }
    if ( !is_null($current) ) {
        $result[] = $current;
    }
    return $result;
}

打印

array (
  0 => 'String1',
  'String2' => 
  array (
    0 => 'data1',
    1 => 'data2',
    2 => 'data3',
    'data4' => 
    array (
      0 => 'a',
      1 => 'b',
      2 => 'c',
    ),
  ),
  1 => 'String3',
  2 => 'String4',
)

(但肯定会因为格式不正确的琴弦而失败)

或者看一下lexer / parser生成器,例如: PHP_LexerGeneratorPHP_ParserGenerator

答案 2 :(得分:1)

这是<?php namespace App\Http\Controllers; use App\User; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class UsersController extends Controller { public function store(Request $request, User $user) { $this->authorize('delete', $user); $this->validate($request, [ 'firstName' => 'required|min:3', 'lastName' => 'required|min:3', 'displayName' => 'required|min:3', 'emailAddress' => 'required|email|unique:users,email', 'password' => 'required|min:3', 'role' => 'required|exists:roles,id' ]); $userRegistered = $user->register( new User($request->all()) ); if ($userRegistered) { flash()->success('Success', 'The user has been successfully created!'); } else { flash()->error('Error', 'The user could not be successfully created!'); } return redirect()->to(route('users')); } } <?php namespace App; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Database\Eloquent\SoftDeletes; class User extends Authenticatable { use SoftDeletes; /** * Fillable fields for a user. * * @var array */ protected $fillable = [ 'first_name', 'last_name', 'display_name', 'email', 'password', 'role_id' ]; /** * The attributes excluded from the model's JSON form. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; public function register(User $user) { return $user->create([ 'first_name' => $user->firstName, 'last_name' => $user->lastName, 'display_name' => $user->displayName, 'email' => $user->emailAdress, 'password' => $user->password, 'role_id' => $user->role ]); } } 的解决方案:

preg_match_all()

eval.in demo

模式说明:

$string = 'String1,String2(data1,data2,data3),String3,String4,String5(data4,data5,data6)';

$pattern = '/([^,(]+)(\(([^)]+)\))?/';

preg_match_all( $pattern, $string, $matches );

$result = array();
foreach( $matches[1] as $key => $val )
{
    if( $matches[3][$key] )
    { $add = explode( ',', $matches[3][$key] ); }
    else
    { $add = $val; }
    $result[$val] = $add;
}

$json = json_encode( $result );