【问题标题】:Regex for circular replacement循环替换的正则表达式
【发布时间】:2011-01-27 14:01:52
【问题描述】:

您将如何使用正则表达式编写函数来执行以下操作:

  1. 用大写字母替换小写字母“a”,反之亦然
    • 如果易于扩展,请对所有字母执行此操作
  2. 如果单词由空格分隔,>< 是某些单词上的特殊标记,请将>word 替换为word<,反之亦然。
    • 如果有帮助,您可以限制输入,以便所有单词都必须以一种或另一种方式标记。
  3. 将后增量 (i++;) 替换为前增量 (++i;),反之亦然。变量名是[a-z]+。现在可以假设输入仅限于这些语句。奖励:也做减量。

也对其他口味的解决方案感兴趣。


注意:这不是家庭作业问题。另请参阅我之前对正则表达式的探索:

【问题讨论】:

  • 这真的适合使用正则表达式吗?
  • 我不知道。我正在尝试探索它的用途和用途。
  • 第一个要求不是正则表达式能做到的。
  • 好的,我将第一个问题简化为一个字母。精神是一样的。
  • @polygenelubricants,冒着听起来像个书呆子的风险,不,精神不一样。你首先说用它的大写或小写等效替换任意字母(正则表达式不可能)。但是,可以替换单个(特定)字母。它们是两种不同的东西。

标签: java regex string replace


【解决方案1】:

最好的方法是使用正则表达式进行匹配,使用回调进行替换。例如。在 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

【讨论】:

  • 我希望 Java 允许回调替换。
【解决方案2】:

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;

【讨论】:

    【解决方案3】:

    正如您无疑已经收集到的那样,做这种事情的唯一明智方法是一次性完成所有替换,根据匹配的内容动态生成替换字符串。

    Java 在当今的主要语言中似乎是独一无二的,因为它没有提供方便的方法来做到这一点,但它可以做到。您只需要使用 Matcher 类提供的较低级别的 API。这是一个基于 Elliott Hughes 明确的 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));
    
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      • 2015-01-24
      相关资源
      最近更新 更多