Найти / заменить массив () с регулярным выражением

Я пытаюсь найти хотя мой код, заменяющий весь старый стиль 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 окно.

0

Решение

Это возможно, но не тривиально, так как вам нужно полностью описать две части синтаксиса 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 используется. Этот параметр содержит количество замен, выполненных в целевой строке.

4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector