2013-07-26 7 views
0

Строка для разбора:улучшить PREG/PCRE/регулярное выражение, чтобы найти PHP переменную

$str = " 
public $xxxx123; 
private $_priv ; 
     $xxx  = 'test'; 
private $arr_123 = array(); 
"; // |  | 
    //  ^^^^^^^---- get the variable name 

Что я до сих пор:

$str = preg_match_all('/\$\S+(;|[[:space:]])/', $str, $matches); 
    foreach ($matches[0] as $match) { 
     $match = str_replace('$', '', $match); 
     $match = str_replace(';', '', $match); 
    } 

Это работает, но я хочу знать , если я могу улучшить preg, например избавиться от двух str_replace и, возможно, включают в себя \t в (;|[[:space:]])

ответ

4

Использование положительного просмотра назад, вы можете получить только то, что вам нужно, чтобы убедиться, что вы будете соответствовать только действительных имен переменных, я использовал этот :

preg_match_all('/(?<=\$)[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',$str,$matches); 
var_dump($matches); 

, который показывает правильно:

 
array (
    0 => 
    array (
    0 => 'xxxx123', 
    1 => '_priv', 
    2 => 'xxx', 
    3 => 'arr_123' 
) 
) 

Это все, что вам нужно, никакая память не таскается на массив, содержащий все переменные с их ведущими и/или хвостовыми символами.

Выражение:

  • (?<=\$) является положительным просмотром назад
  • [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*: это регулярное выражение сайт РНР предлагает себя on their document pages
+0

, это также соответствует другим случайным строкам например, $ ("= §/& =" §/$), и он не будет правильно соответствовать чему-то вроде $ x = 123; –

+0

все равно будет соответствовать, например, здесь «!» § $% & /() =? '" > $% & /() –

+0

ok теперь мы близки к хорошему решению: D –

1

просто использовать обратные ссылки

preg_match_all('/\$(\S+?)[;\s=]/', $str, $matches); 
foreach ($matches[1] as $match) { 

    // $match is now only the name of the variable without $ and ; 
} 
1

Я изменил регулярное выражение немного, посмотрите:

$str = ' 
public $xxxx123; 
private $_priv ; 
     $xxx  = "test"; 
private $arr_123 = array(); 
'; 

$matches = array(); 

//$str = preg_match_all('/\$(\S+)[; ]/', $str, $matches); 
$str = preg_match_all('/\$(\S+?)(?:[=;]|\s+)/', $str, $matches); //credits for mr. @booobs for this regex 

print_r($matches); 

Выход:

Array 
(
    [0] => Array 
     (
      [0] => $xxxx123; 
      [1] => $_priv 
      [2] => $xxx 
      [3] => $arr_123 
     ) 

    [1] => Array 
     (
      [0] => xxxx123 
      [1] => _priv 
      [2] => xxx 
      [3] => arr_123 
     ) 

) 

Теперь вы можете использовать $matches[1] в петле foreach.

:: Обновление ::

После использования регулярных выражений «/ \ $ ([A-Za-Z_ \ x7f- \ XFF] [A-Za-z0-9_ \ x7f- \ XFF] *)/«Результат выглядит корректно.

Строка:

$str = ' 
public $xxxx123; $input1;$input3 
private $_priv ; 
     $xxx  = "test"; 
private $arr_123 = array(); 

«;

И выход:

Array 
(
    [0] => Array 
     (
      [0] => $xxxx123 
      [1] => $input1 
      [2] => $input3 
      [3] => $_priv 
      [4] => $xxx 
      [5] => $arr_123 
     ) 

    [1] => Array 
     (
      [0] => xxxx123 
      [1] => input1 
      [2] => input3 
      [3] => _priv 
      [4] => xxx 
      [5] => arr_123 
     ) 

) 
+0

Я бы изменить регулярное выражение даже более того, что он соответствует, даже если перед оператором присваивания нет места: '\ $ (\ S +?) (?: [=;] | \ s +)' – nstCactus

+0

проблема здесь: '$ input; $ input2; 'он не соответствует' $ input2; ' – DanFromGermany

+0

@sbooob Приятный, я буду менять регулярное выражение. – Benz

Смежные вопросы