2013-04-11 2 views
4

Я хочу, чтобы заменить определение функции и декларации с помощью Regex, т.е.Заменить функцию Java с помощью регулярных выражений: соответствие вложенных скобок

заменить

public abstract void myFuction(MyParam myParam); 

или

@Override 
public void myFuction(MyParam myParam){ 

} 

Я пытался с этим regex:

(@Override[\n\s\t]*)?public *(abstract)? *void 
*generateProcessMethod *\(UIGenerationContext *[^)]+\)[\n\\s\t]*((\{[^{}]*?\})|;) 

Но проблема в том, что функция имеет любые другие { или }, тогда это не сработает.

Замена [^{}] на . не является решением проблемы, так как оно также заменяет следующие функции.

+1

Инструменты распознавания синтаксиса, такие как JavaCC и ANTLR, вероятно подходят для вашей задачи –

+0

, если у вас есть окончательное издание intellij idea, у них очень мощный инструмент поиска и замены структур, который делает именно то, что вам нужно. –

+0

Вы также можете взглянуть на JDT API Eclipse. – SpaceTrucker

ответ

0

Я боюсь, что это невозможно, используя только RegExpressions.

Если понимать вас правильно, вы должны переформатировать некоторый синтаксис, и я предполагаю, что код должен еще быть скомпилирован, в этом случае вам нужно будет противостоять, что увеличивает для каждого { и уменьшается для каждого } так что вы знаете, когда функция заканчивается. Альтернативой может быть возвращение к первому найденному } после того, как вы столкнетесь с следующей декларацией, но было бы много исключений для обработки, например, когда заканчивается класс и т. Д.

Я предлагаю вам использовать синтаксический анализ Java для этой работы он сможет распознать метод как метод и избавит вас от большой работы, посмотрите на javaparser, например

+0

Я не могу просто добавить это .. Я хочу сделать то же самое для некоторых других файлов, имеющих такое же определение, с изменением позиции –

1

Regex не подходит для работы с вложенными компонентами. Тем не менее, если вы знаете, за то, что @Override будет отступом же, как и закрывающей скобки, и все его содержимое с отступом дальше, вы можете использовать это:

([\t\s]+)@Override.*?\n\1} 
+0

Я не могу просто добавить это .. Я хочу сделать то же самое для некоторых других файлов, имеющих такое же определение, с изменением в позиции –

+0

@Abin, только потому, что вы хотите что-то не означает, что RegEx может это выполнить. Я имею в виду, что это * довольно волшебный, но ... есть, к сожалению, ограничения, и это, вероятно, самый большой. –

6

Использование регулярных выражений, это (кронштейн вложенности) делает можно сделать, но только до фиксированного уровня гнездования.

Ваше текущее регулярное выражение (немного изменился):

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*((\{[^\{\}]*?\})|;) 

только позволяет один уровень. Более конкретно, это та часть, которая соответствует его:

(\{[^\{\}]*?\}) 

Если вы хотите, чтобы соответствовать до двух уровней, изменить указанную часть к:

(\{([^{}]*|\{[^{}]*\})*\}) 

Таким образом:

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*(\{([^{}]*|\{[^{}]*\})*\}|;) 

Чтобы добавить дополнительные уровни, вы должны продолжать редактирование. Это будет получить messier и messier, как вы добавляете уровни.

Объяснение:

  • \{ будет соответствовать первой открывающая скобка
    • ( открывает группу
      • [^{}]* матчи ничего, кроме скобок
      • | или
      • \{, если он не найдет открывающую скобку ...
        • [^{}]* ... он будет соответствовать ничего, кроме кронштейна ...
      • \} ... до тех пор, пока не найдет закрывающую скобку
    • ) закрывает группы
    • * выше группа может случиться ноль или более раз
  • \} соответствует окончанию кронштейна

Чтобы добавить больше уровней, изменить средний (вторую) [^{}]* части к ([^{}]*|\{[^{}]*\})*.

Если вы не можете предсказать максимальный уровень вложенности:

Есть некоторые языки, которые позволяют оператору вложенности R, что позволяет вам гнездовой произвольное количество уровней. Если ваш язык не поддерживает его (Java не делает, афаик PHP и Perl do), вам нужно либо:

  • предсказывать максимальный уровень гнездования; ИЛИ
  • самостоятельно создайте парсер.

Регулярные выражения, без оператора R, не может гнездо произвольное количество уровней.

Тем не менее, с помощью оператора R будет как таковой:

(\{([^{}]|(?R))*\}) 

Больше информации на this answer.

+0

Я не могу добавить каждый уровень .. потому что у меня есть несколько файлов с одинаковой функцией - иногда функция может открывать и закрывать (например, для циклов или группировки), это зависит от того, как функция реализована здесь, я могу только угадать функцию имеет одно и то же имя и параметр и '{' '}'. –

+0

Если вы можете определить максимальный уровень вложенности, вы можете использовать это решение. –

+0

Есть несколько языков, которые позволяют оператору вложения «R», который позволяет вам устанавливать произвольное количество уровней. Если ваш язык не поддерживает его (Java не работает, афайк PHP и Perl), вам придется либо предсказать максимальный уровень вложенности, либо создать парсер самостоятельно. Regex, без оператора 'R', ** не может ** установить любое количество уровней. – acdcjunior

1

Нормальные регулярные выражения, как уже указывалось, не имеют возможности делать то, что вам нужно.

Вы можете, однако, использовать Perl 6, что позволяет создавать рекурсивную структуру рисунка. В один момент была предложена возможность согласования вложенных скобок, но Ларри Стена отвергла эту идею.Тем не менее, он предоставил своего рода эскиз того, как рекурсивное сопоставление может быть использовано для достижения по существу одной и той же цели: http://www.perl.com/pub/2002/06/04/apo5.html?page=24#rfc 145: bracematching for perl регулярные выражения

(Честно говоря, я не уверен, почему он не просто предпочитают использовать простой счетчик для каждого типа кронштейнов, но ... я не Ларри Уолл.)

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