Замена переменных номеров элементов ... regex? - PullRequest
0 голосов
/ 16 декабря 2009

Хорошо ... У меня есть неудовлетворительное решение проблемы.

Проблема в том, что у меня есть такой ввод:

{sup 19}F({sup 3}He,t){sup 19}Ne(p){sup 18}F

и нужно выводить так:

¹⁹F(³He,t)¹⁹Ne(p)¹⁸F 

Сначала я использую серию замен, чтобы разбить каждую из секций {sup xx} на {sup x} {sup x}, а затем использую регулярное выражение для сопоставления каждой из них и заменяю символы их единичными эквивалентами UTF-8. , «Проблема» в том, что разделы {sup} могут иметь номера длиной 1, 2 или 3 цифры (может быть, больше, я не знаю), и я хочу «развернуть» их в отдельные разделы {sup} по одной цифре в каждой , (У меня также есть та же проблема с {sub} для подписчиков ...)

Мое текущее решение выглядит так (в Java):

retval = retval.replaceAll("\\{sup ([1-9])([0-9])\\}", "{sup $1}{sup $2}");
retval = retval.replaceAll("\\{sup ([1-9])([0-9])([0-9])\\}", "{sup $1}{sup $2}{sup $3}");

Мой вопрос: есть ли способ сделать это за один проход, независимо от того, сколько цифр (или хотя бы какое-нибудь разумное число) существует?

Ответы [ 3 ]

3 голосов
/ 16 декабря 2009

Да, но это может быть чем-то вроде взлома, и вы должны быть осторожны, это не перебор !

Regex:

(?:\{sup\s)?(\d)(?=\d*})}?

Строка замены:

{sup $1}

Краткое объяснение:

(?:                            | start non-capturing group 1
  \{                           |   match the character '{'
  sup                          |   match the substring: "sup"
  \s                           |   match any white space character
)                              | end non-capturing group 1
?                              | ...and repeat it once or not at all
(                              | start group 1
  \d                           |   match any character in the range 0..9
)                              | end group 1
(?=                            | start positive look ahead
  \d                           |   match any character in the range 0..9
  *                            |   ...and repeat it zero or more times
  }                            |   match the substring: "}"
)                              | stop negative look ahead
}                              | match the substring: "}"
?                              | ...and repeat it once or not at all

На простом английском языке: он соответствует одной цифре, только если смотреть вперед, есть } с дополнительными цифрами между ними. Если возможно, подстроки {sup и } также заменяются.

EDIT:

Лучше вот что:

(?:\{sup\s|\G)(\d)(?=\d*})}?

Таким образом, цифры, как в строке "set={123}", не будут заменены. \G во втором регулярном выражении соответствует месту, где закончился предыдущий матч.

1 голос
/ 16 декабря 2009

Самый простой способ сделать это - использовать PHP-делегаты preg_replace_callback или .NET MatchEvaluator. В Java нет ничего подобного, но он предоставляет API более низкого уровня, который позволяет вам реализовать его самостоятельно. Вот один из способов сделать это:

import java.util.regex.*;

public class Test
{
  static String sepsup(String orig)
  {
    Pattern p = Pattern.compile("(\\{su[bp] )(\\d+)\\}");
    Matcher m = p.matcher(orig);
    StringBuffer sb = new StringBuffer();
    while (m.find())
    {
      m.appendReplacement(sb, "");
      for (char ch : m.group(2).toCharArray())
      {
        sb.append(m.group(1)).append(ch).append("}");
      }
    }
    m.appendTail(sb);
    return sb.toString();
  }

  public static void main (String[] args)
  {
    String s = "{sup 19}F({sup 3}He,t){sub 19}Ne(p){sup 18}F";
    System.out.println(s);
    System.out.println(sepsup(s));
  }
}

результат:

{sup 19}F({sup 3}He,t){sub 19}Ne(p){sup 18}F
{sup 1}{sup 9}F({sup 3}He,t){sub 1}{sub 9}Ne(p){sup 1}{sup 8}F

Если вы хотите, вы можете сгенерировать надстрочный и подстрочный символы и вставить их вместо этого.

0 голосов
/ 16 декабря 2009

Конечно, это стандартная конструкция регулярного выражения. Вы можете узнать обо всех метасимволах в шаблоне Javadoc , но для ваших целей вам, вероятно, понадобится метасимвол "+" или жадный квантификатор {1,3}. Подробности в ссылке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...