Java使用正则表达式替换多个字符

huangapple go评论68阅读模式
英文:

Java replace multiplet characters using regular expression

问题

我正在尝试编写一个字符串替换方法,它可以工作,但在同一个字符串上使用多个替换方法看起来不太好。相信我可以在这里使用正则表达式。

List<String> strng = Collections.singletonList(answer.toString()
        .replaceAll("[,]", "/")
        .replaceAll("[#&]", " ")
        .replaceAll("[*]", "")
        .replaceAll("&", "")
        .replaceAll("]", ""));

我想只使用一个replace()或者replaceAll()方法。简而言之,尝试构造一个正则表达式来替换这些字符 , # * & ]

英文:

I am trying to write a String replace method , it works but looks bad using multiple replace methods on same string. Pretty sure I could use a regular expression here.

        List&lt;String&gt;  strng = Collections.singletonList(answer.toString()
                .replace(&quot;,&quot;, &quot;/&quot;)
                .replace(&quot;#&quot;&quot;, &quot; &quot;)
                .replace(&quot;*&quot;, &quot;&quot;)
                .replace(&quot;&amp;&quot;, &quot;&quot;)
                .replace(&quot;]&quot;, &quot;&quot;));

I would like to use just 1 replace() or replaceAll() method.
in short trying to construct a Regular expression to replace these characters , # * & ]

答案1

得分: 1

简单的正则表达式替换操作不支持在一次操作中进行条件替换。

使用最近的JDK并启用“preview-features”,您可以这样做:

static final Pattern SPECIAL_CHARS = Pattern.compile("[,#*&\\]]");
List<String> strng = List.of(
    SPECIAL_CHARS.matcher(answer.toString())
        .replaceAll(mr -> switch(mr.group().charAt(0)) {
            case ',' -> "/";
            case '#' -> " ";
            default -> "";
        }));

一个兼容Java 8的等效方法会更详细:

static String replaceSpecialChars(String input) {
    Matcher m = SPECIAL_CHARS.matcher(input);
    if(!m.find()) return input;
    StringBuffer sb = new StringBuffer(input.length());
    do {
        String s;
        switch(m.group().charAt(0)) {
            case ',': s = "/"; break;
            case '#': s = " "; break;
            default: s = "";
        }
        m.appendReplacement(sb, s);
    } while(m.find());
    return m.appendTail(sb).toString();
}

尽管这些方法可以一次完成操作,但您需要一个非常大的输入字符串才能从中受益。否则,您的一系列普通(非正则表达式)replace调用可能更有效。您甚至可以将前两个替换从String更改为char的替换,即.replace(',', '/').replace('#', ' ')。由于其他三个具有相同的替换,它们可以被单个.replaceAll("[*&\\]]", "")替换,但正如前面所说,使用正则表达式引擎不一定比多个纯文本替换操作更有效。

英文:

Simple regex replacement operations do not support conditional replacements in one operation.

With a recent JDK and “preview-features” enabled, you could do as

static final Pattern SPECIAL_CHARS = Pattern.compile(&quot;[,#*&amp;\\]]&quot;);
List&lt;String&gt; strng = List.of(
    SPECIAL_CHARS.matcher(answer.toString())
        .replaceAll(mr -&gt; switch(mr.group().charAt(0)) {
            case &#39;,&#39; -&gt; &quot;/&quot;;
            case &#39;#&#39; -&gt; &quot; &quot;;
            default -&gt; &quot;&quot;;
        }));

A Java 8 compatible equivalent would be more elaborated:

static String replaceSpecialChars(String input) {
    Matcher m = SPECIAL_CHARS.matcher(input);
    if(!m.find()) return input;
    StringBuffer sb = new StringBuffer(input.length());
    do {
        String s;
        switch(m.group().charAt(0)) {
            case &#39;,&#39;: s = &quot;/&quot;; break;
            case &#39;#&#39;: s = &quot; &quot;; break;
            default: s = &quot;&quot;;
        }
        m.appendReplacement(sb, s);
    } while(m.find());
    return m.appendTail(sb).toString();
}

While these approaches perform the operation in one go, you’d need a really large input string to draw a benefit from that. Otherwise, your chain of plain (non-regex) replace calls is likely to be more efficient. You could even replace the first two from String to char replacements, i.e. .replace(&#39;,&#39;, &#39;/&#39;).replace(&#39;#&#39;, &#39; &#39;). Since the other three have the same replacement, they could get replaced by a single .replaceAll(&quot;[*&amp;\\]]&quot;, &quot;&quot;) but as said, using the regex engine is not necessarily more efficient than multiple plain text replacement operations.

答案2

得分: 0

以下是翻译好的部分:

最后三个调用可以使用正则表达式进行替换,如下所示:

List<String> strng = Collections.singletonList(answer.toString()
                    .replace(",", "/")
                    .replace("#", " ")
                    .replaceAll("[\\*&\\]]", ""));

正则表达式 [\\*&\\]] 指定了任何一个 *&]。从 这里 了解更多关于字符类的信息。

演示:

public class Main {
    public static void main(String[] args) {
        String str = "Hello,Hi#Bye*World&Welcome]Good";
        System.out.println(str
                            .replace(",", "/")
                            .replace("#", " ")
                            .replaceAll("[\\*&\\]]", ""));
    }
}

输出:

Hello/Hi ByeWorldWelcomeGood
英文:

The last three calls can be replaced with one call by using regex as shown below:

List&lt;String&gt;  strng = Collections.singletonList(answer.toString()
                .replace(&quot;,&quot;, &quot;/&quot;)
                .replace(&quot;#&quot;, &quot; &quot;)
                .replaceAll(&quot;[\\*&amp;\\]]&quot;, &quot;&quot;));

The regex, [\\*&amp;\\]] specifies any of *, &amp; or ]. Learn more about character classes from here.

Demo:

public class Main {
	public static void main(String[] args) {
		String str = &quot;Hello,Hi#Bye*World&amp;Welcome]Good&quot;;
		System.out.println(str
							.replace(&quot;,&quot;, &quot;/&quot;)
							.replace(&quot;#&quot;, &quot; &quot;)
							.replaceAll(&quot;[\\*&amp;\\]]&quot;, &quot;&quot;));
	}
}

Output:

Hello/Hi ByeWorldWelcomeGood

答案3

得分: 0

如果您恰好使用Apache Commons库,您可以使用StringUtils类中的方法replaceChars

replaceChars(String str, String searchChars, String replaceChars)

但仅仅因为一个方法而导入整个库,在我看来有些多余。

String str = "foobar,123#xyz*abc&amp;def]";
String res = StringUtils.replaceChars(str, ",#*&amp;]", "/ ");
System.out.println(res);

//输出:foobar/123 xyzabcdef
英文:

If you happen to use the Apache Commons library you can use the method replaceChars

replaceChars(String str, String searchChars, String replaceChars)

from the StringUtils class. But just because of the one method to include the library would be superfluous in my opinion.

String str = &quot;foobar,123#xyz*abc&amp;def]&quot;;
String res = StringUtils.replaceChars(str, &quot;,#*&amp;]&quot;, &quot;/ &quot;);
System.out.println(res);

//output : foobar/123 xyzabcdef 

答案4

得分: 0

将其分成两个部分。

  1. 删除所有字符(用空字符串替换(&quot;&quot;)。使用 String::replaceAll 与一个正则表达式定义的一组要删除的字符:answer.replaceAll(&quot;[*&amp;\\]]&quot;, &quot;&quot;)
  2. 准备两个字符串,分别包含替换之前和之后的字符。确保这两个字符串的长度相同,并且每个字符都恰好被另一个字符替代(根据您的问题)。您可以使用 String[] 来实现这个目的。遍历字符并在原始字符串中进行替换。
String[] mapping = {&quot;,#&quot;, &quot;  &quot;};

// 下面的代码保持不变,不管有多少次替换
String newAnswer = IntStream.range(0, mapping[0].length()).boxed().reduce(
    answer.replaceAll(&quot;[*&amp;\\]]&quot;, &quot;&quot;),
	(str, i) -&gt; str.replace(mapping[0].charAt(i), mapping[1].charAt(i)),
	(l, r) -&gt; l);

如您所见,IntStream.range(int, int) 很方便。此外,您可以将删除结果本身用作 reduce 操作的“identity”。


**免责声明:**此解决方案仅适用于需要删除大量字符以避免重复的情况。否则,一系列的 String::replace 更加合适。

英文:

Divide it into two parts.

  1. Remove all the characters (replacement with an empty string (&quot;&quot;). Use String::replaceAll with a Regex defining a set of characters to be removed: answer.replaceAll(&quot;[*&amp;\\]]&quot;, &quot;&quot;).
  2. Have two strings ready containing the characters before replacement and after. Enforce the same length of both strings and a rule that each character is subsituted with exactly one another (according to your question). You can use String[] for this purpose. Iterate through the characters and replace them in the original string.
String[] mapping = {&quot;,#&quot;, &quot;  &quot;};

// The advantage is the code below remains the same regardles the number or replacements
String newAnswer = IntStream.range(0, mapping[0].length()).boxed().reduce(
    answer.replaceAll(&quot;[*&amp;\\]]&quot;, &quot;&quot;),
	(str, i) -&gt; str.replace(mapping[0].charAt(i), mapping[1].charAt(i)),
	(l, r) -&gt; l);

As you can see, IntStream.range(int, int) comes handy. Moreover, you can use the removal result itself as an identity of the reduce operation.


Disclaimer: The solution is suitable only for a large set of characters to be removed to avoid repetitions. Otherwise a chain of String::replace is more than suitable.

huangapple
  • 本文由 发表于 2020年9月16日 03:54:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63908978.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定