繁体   English   中英

正则表达式用空格替换部分字符串

[英]Regex to replace part of the string with spaces

看起来很简单,但我无法让它发挥作用。

我有一个看起来像'NNDDDDDAAAA'的字符串,其中'N'是非数字,'D'是数字,'A'是任何东西。 我需要用空格字符替换每个A. 输入字符串中的'N','D'和'A'的数量总是不同的。

我知道如何使用两个表达式来完成它。 我可以将一个字符串拆分为两个,然后用空格替换第二组中的所有内容。 像这样

    Pattern pattern = Pattern.compile("(\\D+\\d+)(.+)");
    Matcher matcher = pattern.matcher(input);
    if (matcher.matches()) {
        return matcher.group(1) + matcher.group(2).replaceAll(".", " ");
    }

但我想知道是否有可能使用单个正则表达式。

鉴于你的描述,我假设在NNDDDDD部分之后,第一个A实际上是N而不是A ,因为否则DDDDDAAAA部分之间没有固定的边界。

因此,您的字符串实际上看起来像NNDDDDDNAAA ,并且您想要用空格替换NAAA部分。 鉴于此,正则表达式可以这样重写: (\\\\D+\\\\d+)(\\\\D.+)

Java中的正面lookbehind需要固定长度模式; 您不能使用+*模式。 您可以改为使用花括号并指定最大长度。 例如,您可以使用{1,9}代替每个+ ,它将匹配1到9个字符: (?<=\\\\D{1,9}\\\\d{1,9})(\\\\D.+)

这里唯一的问题是你将NAAA序列作为单个匹配进行匹配,因此使用"NNNDDDDNAAA".replaceAll("(?<=\\\\D{1,9}\\\\d{1,9})(\\\\D.+)", " ")将导致用单个空格而不是多个空格替换整个NAAA序列。

您可以使用匹配的开始分隔符和字符串长度,并使用它来附加正确数量的空格,但我没有看到这一点。 我认为你的原始解决方案会更好; 它简单易懂。

如果你正在寻找一些额外的速度,你可以在函数外编译你的Pattern,并使用StringBuilder或StringBuffer来创建你的输出。 如果您正在构建所有这些NNDDDDDAAAAA元素中的大型String,请完全使用StringBuilder,直到您完成追加为止。

class Test {

public static Pattern p = Pattern.compile("(\\D+\\d+)(\\D.+)");

public static StringBuffer replace( String input ) {
    StringBuffer output = new StringBuffer();
    Matcher m = Test.p.matcher(input);
    if( m.matches() )
        output.append( m.group(1) ).append( m.group(2).replaceAll("."," ") );

    return output;
}

public static void main( String[] args ) {
    String input = args[0];
    long startTime;

    StringBuffer tests = new StringBuffer();
    startTime = System.currentTimeMillis();
        for( int i = 0; i < 50; i++)
        {
            tests.append( "Input -> Output: '" );
            tests.append( input );
            tests.append( "' -> '" );
            tests.append( Test.replace( input ) );
            tests.append( "'\n" );
        }
    System.out.println( tests.toString() );
    System.out.println( "\n" + (System.currentTimeMillis()-startTime));
}

}

更新:我写了一个快速的迭代解决方案,并通过两者运行一些随机数据。 迭代解决方案的速度提高了4-5倍。

public static StringBuffer replace( String input )
{
    StringBuffer output = new StringBuffer();
    boolean second = false, third = false;
    for( int i = 0; i < input.length(); i++ )
    {
        if( !second && Character.isDigit(input.charAt(i)) )
            second = true;

        if( second && !third && Character.isLetter(input.charAt(i)) )
            third = true;

        if( second && third )
            output.append( ' ' );
        else
            output.append( input.charAt(i) );

    }

    return output;
}

nondigit vs what是什么意思?

[^a-zA-Z0-9]
匹配不是字母或数字的所有内容。

你想要用空格替换上面的正则表达式匹配的任何东西。

这就是你在说什么?

你想使用积极的外观来匹配N和D,然后使用A的正常匹配。

不确定Java中语法背后的积极外观,但有些关于Java正则表达式的文章有所了解

我知道你要求正则表达式,但为什么你甚至需要一个正则表达式呢? 怎么样:

StringBuilder sb = new StringBuilder(inputString);
for (int i = sb.length() - 1; i >= 0; i--) {
    if (Character.isDigit(sb.charAt(i)))
        break;
    sb.setCharAt(i, ' ');
}
String output = sb.toString();

你可能会觉得这篇文章很有趣。 当然,上面的代码假定字符串中至少有一个数字 - 最后一个数字后面的所有字符都被转换为空格。 如果没有数字,则每个字符都转换为空格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM