3

一个字符串可以在小写字母中包含一对多括号,就像String content = "This is (a) nightmare";我想将字符串转换为"<centamp>This is </centamp>(a) <centamp>nightmare</centamp>";所以基本上在这个字符串周围添加 centamp 标记,但如果它的括号中有一个小写字母,则应该从标记中排除。

这是我到目前为止所尝试的,但它没有达到预期的结果。一个字符串中可能没有很多括号,并且每个括号都应该将其从标记中排除。

Pattern pattern = Pattern.compile("^(.*)?(\\([a-z]*\\))?(.*)?$", Pattern.MULTILINE);    
String content = "This is (a) nightmare";
System.out.println(content.matches("^(.*)?(\\([a-z]*\\))?(.*)?$"));
System.out.println(pattern.matcher(content).replaceAll("&lt;centamp&gt;$1$3&lt;/centamp&gt;$2"));
4

3 回答 3

2

这可以一次性完成replaceAll

String outputString =
    inputString.replaceAll("(?s)\\G((?:\\([a-z]+\\))*+)((?:(?!\\([a-z]+\\)).)+)",
                           "$1<centamp>$2</centamp>");

它允许括号内的小写英文字母字符的非空\\([a-z]+\\)序列。

特征:

  • 仅空白序列被标记。
  • 空字符串周围不会有标签。

解释:

  • \G断言匹配边界,即下一个匹配只能从最后一个匹配的结尾开始。它还可以匹配字符串的开头(当我们还没有找到任何匹配时)。

  • 正则表达式的每个匹配项都将包含以下序列:0 个或多个连续的\\([a-z]+\\)(之间不允许有空格),并且后跟至少 1 个不形成\\([a-z]+\\)序列的字符。

    • 0个或多个连续\\([a-z]+\\)覆盖字符串不以开头\\([a-z]+\\)的情况,以及字符串不包含的情况\\([a-z]+\\)

      在这部分的模式中(?:\\([a-z]+\\))*+- 请注意+after*使量词具有所有格,换句话说,它不允许回溯。简单地说,优化。

    • 一个字符限制是必要的,以防止添加包含空字符串的标签。

      在这部分的模式中- 请注意,对于每个字符,我在匹配它之前(?:(?!\\([a-z]+\\)).)+检查它是否是模式的一部分。\\([a-z]+\\)(?!\\([a-z]+\\)).

  • (?s)flag 将导致.匹配任何字符,包括换行符。这将允许标签包含跨越多行的文本。

于 2013-05-14T18:45:06.337 回答
1

您只需用 </centamp>$1<centamp> 替换所有出现的“([az])”,然后添加 <centamp> 并附加 </centamp>

String content = "Test (a) test (b) (c)";
Pattern pattern = Pattern.compile("(\\([a-z]\\))");
Matcher matcher = pattern.matcher(content);
String result = "&lt;centamp&gt;" + matcher.replaceAll("&lt;/centamp&gt;$1&lt;centamp&gt;") + "&lt;/centamp&gt;";

注意我在浏览器中写了上面的内容,因此可能存在语法错误。

编辑这是一个完整的示例,其中包含最简单的正则表达式。

import java.util.*;
import java.lang.*;
import java.util.regex.*;
class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
        String content = "test (a) (b) and (c)";
        String result = "<centamp>" + 
            content.replaceAll("(\\([a-z]\\))", "</centamp>$1<centamp>") +
            "</centamp>";
        result = result.replaceAll("<centamp></centamp>", "");
        System.out.print(result);
    }
}
于 2013-05-14T18:55:52.120 回答
0

这是另一种使用更清洁的正则表达式的解决方案。该解决方案更长,但它允许更灵活地调整添加标签的条件。

这里的想法是匹配包含小写字符的括号(我们不想标记的部分),然后使用匹配中的索引来标识我们想要包含在标记中的部分。

// Regex for the parenthesis containing only lowercase English
// alphabet characters
static Pattern REGEX_IN_PARENTHESIS = Pattern.compile("\\([a-z]+\\)");

private static String addTag(String str) {
    Matcher matcher = REGEX_IN_PARENTHESIS.matcher(str);
    StringBuilder sb = new StringBuilder();

    // Index that we have processed up to last append into StringBuilder
    int lastAppend = 0;

    while (matcher.find()) {
        String bracket = matcher.group();

        // The string from lastAppend to start of a match is the part
        // we want to tag
        // If you want to, you can easily add extra logic to process
        // the string
        if (lastAppend < matcher.start()) { // will not tag if empty string
            sb.append("<centamp>")
              .append(str, lastAppend, matcher.start())
              .append("</centamp>");
        }

        // Append the parenthesis with lowercase English alphabet as it is
        sb.append(bracket);

        lastAppend = matcher.end();
    }

    // The string from lastAppend to end of string (no more match)
    // is the part we want to tag
    if (lastAppend < str.length()) {
        sb.append("<centamp>")
          .append(str, lastAppend, str.length())
          .append("</centamp>");
    }

    return sb.toString();
}
于 2013-05-14T19:55:39.990 回答