1

我在 Java 中有以下函数,它接受字符串注释并返回注释,但所有尾随#字符和#删除后有空格的任何字符,以及多个相邻主题标签的任何序列,例如###,替换为单个#字符。这是代码段

private static String replaceHashTagsAndPunctuation(String comment) {
// Remove trailing '#' values
comment = comment.replaceAll("#*$", "");

// Replace instances of multiple '#' values with one '#'
comment = comment.replaceAll("#+", "#");


// Remove punctuation
comment = comment.replaceAll("[^a-zA-Z0-9 #]", "");

// Remove all hashtags that have no word after them
comment = comment.replaceAll("# ", "");

return comment;
}

这是非常冗长和丑陋的。所以我的问题是:
如何使用更好的正则表达式语句重写它以在一两行中删除字符串的所有这些部分?
此外,对您建议的正则表达式代码为何起作用的解释将帮助我更好地理解正则表达式在 Java 中的工作原理。

4

4 回答 4

1

理念一

这将如何替换您的两个电话:

comment = comment.replaceAll("#+([ #])", $1);

通过将尾随空格留在那里,这与您所拥有的两个略有不同:

comment = comment.replaceAll("#+", "#");
comment = comment.replaceAll("# ", "");

我不知道删除尾随空格是否很重要,因为您的话说“删除任何 # 后面有空格”,但没有说删除空格。但是,代码确实将其删除。

想法 2

它增加了一些复杂性,但您可以通过以下方式处理其中三个:

comment = comment.replaceAll("#+([ #]|$)", $1);

解释

第二$1个参数中的 表示您将匹配的字符串替换为与括号内的部分匹配的任何部分。

[ #]表示空格或数字符号。

一起[# ]|$表示空格、数字符号或字符串的结尾。

于 2013-05-31T17:37:52.660 回答
1

代码本身没有错,但它可能会被分解。

例如:

// LinkedHashMap: insertion order matters!
private static final Map<Pattern, String> REPLACEMENTS
    = new LinkedHashMap<Pattern, String>();

static {
    Pattern pattern;
    String replacement;

    pattern = Pattern.compile("#*$");
    replacement = "";
    REPLACEMENTS.put(pattern, replacement);

    pattern = Pattern.compile("#+");
    replacement = "#";
    REPLACEMENTS.put(pattern, replacement);

    // etc
}

那么你的代码可能是:

private static String replaceHashTagsAndPunctuation(final String comment)
{
    String ret = comment;

    for (final Map.Entry<Pattern, String> entry: REPLACEMENTS.entrySet())
        ret = entry.getKey().matcher(ret).replaceAll(entry.getValue());

    return ret;
}
于 2013-05-31T17:45:07.660 回答
0

您只需清理一次:

comment = comment.replaceAll("#+", "#").replaceAll("[^a-zA-Z0-9 #]|# |#*$", "");

正则表达式中的 Bar 表示OR.

于 2013-05-31T17:35:41.737 回答
0

好吧,首先,我认为您的起始正则表达式清晰易懂且可靠,这是正则表达式中罕见且有价值的功能,因此如果我在我正在编写的代码中看到这一点,我不会更改它。李的单线:

comment = comment.replaceAll("#+([ #]|$)", $1);

紧凑、正确、聪明,但乍一看很难完全理解。虽然我认为自己是 regex 方面的专家,但我仍然需要停下来思考并解开正则表达式中编码的 3 个案例,以弄清楚它会做什么。

如果您想在不走极端的情况下美化您的代码,我建议:

// Replace instances of 1 or more consecutive '#' values with a single '#'
comment = comment.replaceAll("#{1,}", "#");  // 1

// Strip out '#' followed by space or at end of line
comment = comment.replaceAll("#( |$)", "");  // 2
  1. 用单个“#”替换 1 个或多个“#”
  2. 删除后跟空格或行尾的“#”。这也会删除“#”之后的单个尾随空格。要保留空间,请将替换更改为“$1”。
于 2013-05-31T18:19:38.850 回答