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

0

Я пытаюсь выполнить поиск, хотя мой код заменяет весь старый стиль PHP array() стилем shorthand []. Однако у меня возникают проблемы с созданием рабочего/надежного регулярного выражения...

В настоящее время у меня есть: (^|[\s])array\((['"](\s\S)['"]|[^)])*\) (View on 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 для этого...

EDIT: Это не ответ на вопрос, но одна из альтернатив заключается в использовании проверенной проверки подлинности Traditional syntax array literal detected PHPStorm....

Как:

  • Откройте меню " Code
  • Нажмите " Run inspection by name... (Ctrl + Alt + Shift + I)
  • Тип: Traditional syntax array literal detected
  • Нажмите <Enter>
  • Укажите область, в которой вы хотите ее запустить.
  • Нажмите <Enter>
  • Просмотрите/Внесите изменения в окно Inspection.
Теги:
arrays

1 ответ

4
Лучший ответ

Это возможно, но не тривиально, поскольку вам нужно полностью описать две части синтаксиса 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)...) и содержит именованные определения подшаблонов для разных полезных элементов (в частности, "строка" "com" и "nestedpar"). Эти подшаблоны будут использоваться позже в основном шаблоне.

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

Первая строка: (?:\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 while используется для обработки объявлений вложенных массивов, поскольку невозможно выполнить замену нескольких уровней вложенности за один проход (однако есть путь с preg_replace_callback но это не очень удобно). Чтобы остановить цикл, используется последний параметр preg_replace. Этот параметр содержит количество замен, выполняемых в целевой строке.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню