Как сопоставить строку в круглых скобках (вложенных) в Java?
Я хотел бы сопоставить строку в скобках, как:
(i, j, k(1))
^^^^^^^^^^^^
Строка также может содержать закрытые скобки. Как сопоставить его с регулярным выражением в Java без написания парсера, так как это небольшая часть моего проекта. Спасибо!
Редактировать:
Я хочу найти строковый блок и найти что-то вроде u(i, j, k)
, u(i, j, k(1))
или просто u(<anything within this paired parens>)
и заменить их на __u%array(i, j, k)
а также __u%array(i, j, k(1))
для моего приложения для перевода на Фортран.
3 ответа
Как я уже сказал, вопреки распространенному мнению (не верьте всему, что говорят люди), сопоставление вложенных скобок возможно с регулярным выражением.
Недостатком его использования является то, что вы можете только до фиксированного уровня вложенности. И для каждого дополнительного уровня, который вы хотите поддерживать, ваше регулярное выражение будет все больше и больше.
Но не верьте мне на слово. Позволь мне показать тебе. Регулярное выражение:
\([^()]*\)
Соответствует одному уровню. Для двух уровней вам понадобится:
\(([^()]*|\([^()]*\))*\)
И так далее. Чтобы продолжать добавлять уровни, все, что вам нужно сделать, это изменить средний (второй) [^()]*
часть к ([^()]*|\([^()]*\))*
( проверьте три уровня здесь). Как я уже сказал, он будет все больше и больше.
Твоя проблема:
Для вашего случая может быть достаточно двух уровней. Таким образом, Java-код для этого будет:
String fortranCode = "code code u(i, j, k) code code code code u(i, j, k(1)) code code code u(i, j, k(m(2))) should match this last 'u', but it doesnt.";
String regex = "(\\w+)(\\(([^()]*|\\([^()]*\\))*\\))"; // (\w+)(\(([^()]*|\([^()]*\))*\))
System.out.println(fortranCode.replaceAll(regex, "__$1%array$2"));
Входные данные:
code code u(i, j, k) code code code code u(i, j, k(1)) code code code u(i, j, k(m(2))) should match this last 'u', but it doesnt.
Выход:
code code __u%array(i, j, k) code code code code __u%array(i, j, k(1)) code code code u(i, j, __k%array(m(2))) should match this last 'u', but it doesnt.
Нижняя линия:
В общем случае парсеры будут работать лучше - вот почему люди так обижаются на это. Но для простых приложений регулярных выражений может быть достаточно.
Примечание: некоторые разновидности регулярных выражений поддерживают оператор вложенности R
(Java не делает, PCRE движки, как PHP и Perl делают), что позволяет вам вкладывать произвольное количество уровней. С ними вы можете сделать: \(([^()]|(?R))*\)
,
Раздели свою работу. Пусть регулярное выражение будет:
([a-z]+)\((.*)\)
Первая группа будет содержать идентификатор, вторая - параметры. Затем действуйте так:
private static final Pattern PATTERN = Pattern.compile("([a-z]+)\\((.*)\\)");
// ...
final Matcher m = Pattern.matcher(input);
if (!m.matches())
// No match! Deal with it.
// If match, then:
final String identifier = m.group(1);
final String params = m.group(2);
// Test if there is a paren
params.indexOf('(') != -1;
замещать [a-z]+
с любым идентификатором может быть в Fortran.
Пожалуйста, проверьте этот ответ, так как он в основном делает то, что вы пытаетесь сделать (короче говоря, это не реально с помощью регулярных выражений)