Регулярное выражение для круговой замены - PullRequest
1 голос
/ 15 марта 2010

Как бы вы использовали регулярные выражения для написания функций, выполняющих следующие действия:

  1. Замените строчную букву 'a' на заглавную и наоборот
    • Если это легко расширяется, сделайте это для всех букв
  2. Если слова разделены пробелами, а > и < являются специальными маркерами в некоторых словах, замените >word на word< и наоборот.
    • Если это помогает, вы можете ограничить ввод таким образом, чтобы все слова были помечены так или иначе.
  3. Замените постинкремент (i++;) на преинкремент (++i;) и наоборот.Имена переменных [a-z]+.Теперь можно предположить, что ввод ограничен кучей этих утверждений.Бонус: также делайте декремент.

Также интересует решения для других вкусов.


Примечание: это НЕ вопрос домашней работы.Смотрите также мои предыдущие исследования регулярных выражений:

Ответы [ 3 ]

2 голосов
/ 15 марта 2010

Как вы, несомненно, поняли, единственный разумный способ сделать подобные вещи - сделать все замены за один проход, генерируя строки замены динамически на основе того, что было найдено.

Java кажется уникальной среди сегодняшних основных языков в том, что не предоставляет удобный способ сделать это, но это можно сделать. Вам просто нужно использовать API более низкого уровня, предоставляемый классом Matcher. Вот демонстрация, основанная на окончательном Rewriter Эллиотта Хьюза:

import java.util.regex.*;

/**
 * A Rewriter does a global substitution in the strings passed to its
 * 'rewrite' method. It uses the pattern supplied to its constructor, and is
 * like 'String.replaceAll' except for the fact that its replacement strings
 * are generated by invoking a method you write, rather than from another
 * string. This class is supposed to be equivalent to Ruby's 'gsub' when
 * given a block. This is the nicest syntax I've managed to come up with in
 * Java so far. It's not too bad, and might actually be preferable if you
 * want to do the same rewriting to a number of strings in the same method
 * or class. See the example 'main' for a sample of how to use this class.
 *
 * @author Elliott Hughes
 */
public abstract class Rewriter
{
  private Pattern pattern;
  private Matcher matcher;

  /**
   * Constructs a rewriter using the given regular expression; the syntax is
   * the same as for 'Pattern.compile'.
   */
  public Rewriter(String regex)
  {
    this.pattern = Pattern.compile(regex);
  }

  /**
   * Returns the input subsequence captured by the given group during the
   * previous match operation.
   */
  public String group(int i)
  {
    return matcher.group(i);
  }

  /**
   * Overridden to compute a replacement for each match. Use the method
   * 'group' to access the captured groups.
   */
  public abstract String replacement();

  /**
   * Returns the result of rewriting 'original' by invoking the method
   * 'replacement' for each match of the regular expression supplied to the
   * constructor.
   */
  public String rewrite(CharSequence original)
  {
    this.matcher = pattern.matcher(original);
    StringBuffer result = new StringBuffer(original.length());
    while (matcher.find())
    {
      matcher.appendReplacement(result, "");
      result.append(replacement());
    }
    matcher.appendTail(result);
    return result.toString();
  }



  public static void main(String... args) throws Exception
  {
    String str = ">Foo baR<";

    // anonymous subclass example:
    Rewriter caseSwapper = new Rewriter("[A-Za-z]")
    {
      public String replacement()
      {
        char ch0 = group(0).charAt(0);
        char ch1 = Character.isUpperCase(ch0) ?
                   Character.toLowerCase(ch0) :
                   Character.toUpperCase(ch0);
        return String.valueOf(ch1);
      }
    };
    System.out.println(caseSwapper.rewrite(str));

    // inline subclass example:
    System.out.println(new Rewriter(">(\\w+)|(\\w+)<")
    {
      public String replacement()
      {
        return group(1) != null ? group(1) + "<"
                                : ">" + group(2);
      }
    }.rewrite(str));

  }
}
1 голос
/ 15 марта 2010

Perl, также используя код в замене:

$\ = $/;

### 1.
$_ = 'fooBAR';

s/\w/lc $& eq $&? uc $&: lc $&/eg;

# this isn't a regex but better (in most cases):
# tr/A-Za-z/a-zA-Z/g;

print;
# FOObar

### 2.
$_ = 'foo >bar baz<';

s/>(\w+)|(\w+)</$1?"$1<":">$2"/eg;

print;
# foo bar< >baz

### 3.
$_ = 'x; ++i; i--;';

s/(--|\+\+)?\b([a-z]\w*)\b(?(1)|(--|\+\+))/$1?"$2$1":"$3$2"/eig;

print;
# x; i++; --i;
1 голос
/ 15 марта 2010

Лучший способ сделать это - использовать регулярное выражение для сопоставления и обратный вызов для замены. Например. в Python:

import re

# First example
s = 'abcDFE'
print re.sub(r'\w', lambda x: x.group().lower()
                              if x.group().isupper()
                              else x.group().upper(), s)
# OUTPUT: ABCdfe

# Second example
s = '<abc dfe> <ghe <auo pio>'
def switch(match):
  match = match.group()
  if match[0] == '<':
    return match[1:] + '>'
  else:
    return '<' + match[:-1]
print re.sub(r'<\w+|\w+>', switch, s)
# OUTPUT: abc> <dfe ghe> auo> <pio
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...