Я пытаюсь найти хотя мой код, заменяющий весь старый стиль PHP array()
с сокращением []
стиль. Тем не менее, у меня возникли проблемы с созданием рабочего / надежного регулярного выражения …
Что у меня сейчас есть: (^|[\s])array\((['"](\s\S)['"]|[^)])*\)
(Смотреть на Regex101)
// Match All
array('array()')
array('key' => 'value');
array(
'key' => 'value',
'key2' => '(value2)'
);
array()
array()
array()
// Match Specific Parts
function (array $var = array()) {}
$this->in_array(array('something', 'something'));
// Don't match
toArray()
array_merge()
in_array();
Я создал Regex101 для этого…
РЕДАКТИРОВАТЬ: Это не ответ на вопрос, но одной из альтернатив является использование PHPStorm Traditional syntax array literal detected
осмотр …
Как:
Code
менюRun inspection by name...
(Ctrl + Alt + Shift + I)Traditional syntax array literal detected
<Enter>
<Enter>
Inspection
окно.Это возможно, но не тривиально, так как вам нужно полностью описать две части синтаксиса PHP (это строки и комментарии), чтобы избежать интерпретации скобок внутри них. Вот способ сделать это с помощью самого PHP:
$pattern = <<<'EOD'
~
(?(DEFINE)
(?<quotes> (["']) (?: [^"'\\]+ | \\. | (?!\g{-1})["'] )*+ (?:\g{-1}|\z) )
(?<heredoc> <<< (["']?) ([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*) \g{-2}\R
(?>\N*\R)*?
(?:\g{-1} ;? (?:\R | \z) | \N*\z)
)
(?<string> \g<quotes> | \g<heredoc> )
(?<inlinecom> (?:// |\# ) \N* $ )
(?<multicom> /\*+ (?:[^*]+|\*+(?!/))*+ (?:\*/|\z))
(?<com> \g<multicom> | \g<inlinecom> )
(?<nestedpar> \( (?: [^()"'<]+ | \g<com> | \g<string> | < | \g<nestedpar>)*+ \) )
)
(?:\g<com> | \g<string> ) (*SKIP)(*FAIL)
|
(?<![-$])\barray\s*\( ((?:[^"'()/\#]+|\g<com>|/|\g<string>|\g<nestedpar>)*+) \)
~xsm
EOD;
do {
$code = preg_replace($pattern, '[${11}]', $code, -1, $count);
} while ($count);
Шаблон состоит из двух частей: первая — это часть определения, а вторая — основной шаблон.
Часть определения заключена между (?(DEFINE)...)
и содержит определения именованных подшаблонов для различных полезных элементов (в частности, «string», «com» и «nestedpar»). Эти подшаблоны будут использоваться позже в основном шаблоне.
Идея состоит в том, чтобы никогда не искать скобки внутри комментария, строки или среди вложенных скобок.
Первая строка: (?:\g<com> | \g<string> ) (*SKIP)(*FAIL)
пропустит все комментарии и строки до следующего объявления массива (или до конца строки).
Последняя строка описывает само объявление массива, детали:
(?<![-$])\b # check if "array" is not a part of a variable or function name
array \s*\(
( # capture group 11
(?: # describe the possible content
[^"'()/\#]+ # all that is not a quote, a round bracket, a slash, a sharp
| # OR
\g<com> # a comment
|
/ # a slash that is not a part of a comment
|
\g<string> # a string
|
\g<nestedpar> # nested round brackets
)*+
)
\)
о объявлениях вложенных массивов:
Данный шаблон может найти только самое внешнее объявление массива, когда найден блок объявлений вложенного массива.
do...while
Цикл используется для работы с объявлениями вложенных массивов, потому что невозможно выполнить замену нескольких уровней вложенности за один проход (однако, есть способ preg_replace_callback
но это не очень удобно). Чтобы остановить цикл, последний параметр preg_replace
используется. Этот параметр содержит количество замен, выполненных в целевой строке.
Других решений пока нет …