看起来很简单,但我无法让它发挥作用。
我有一个看起来像'NNDDDDDAAAA'的字符串,其中'N'是非数字,'D'是数字,'A'是任何东西。我需要用空格字符替换每个A. 我知道如何使用两个表达式来完成它。我可以将一个字符串拆分为两个,然后用空格替换第二组中的所有内容。喜欢这个 但我想知道是否可以使用单个正则表达式。 Pattern pattern = Pattern.compile("(\\D+\\d+)(.+)");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
return matcher.group(1) + matcher.group(2).replaceAll(".", " ");
}
答案 0 :(得分:3)
根据你的描述,我假设在NNDDDDD
部分后,第一个A
实际上是N
而不是A
,否则就没有DDDDD
和AAAA
部分之间的实线边界。
因此,您的字符串实际上看起来像NNDDDDDNAAA
,并且您想要用空格替换NAAA
部分。鉴于此,正则表达式可以这样重写:(\\D+\\d+)(\\D.+)
Java中的正面观察需要固定长度模式;您无法使用+
或*
模式。您可以改为使用花括号并指定最大长度。例如,您可以使用{1,9}
代替每个+
,它将匹配1到9个字符:(?<=\\D{1,9}\\d{1,9})(\\D.+)
这里唯一的问题是你将NAAA序列作为单个匹配进行匹配,因此使用"NNNDDDDNAAA".replaceAll("(?<=\\D{1,9}\\d{1,9})(\\D.+)", " ")
将导致用单个空格而不是多个空格替换整个NAAA
序列。 / p>
您可以使用匹配的起始分隔符和字符串长度,并使用它来附加正确数量的空格,但我没有看到这一点。我认为你的原始解决方案会更好;它简单易懂。
如果您正在寻找一些额外的速度,您可以在函数外部编译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;
}
答案 1 :(得分:1)
你对nondigit和任何东西是什么意思?
[^a-zA-Z0-9]
匹配不是字母或数字的所有内容。
你想要用空格替换上面正则表达式匹配的任何内容。
这就是你在说什么?
答案 2 :(得分:1)
你想在后面使用正面观察以匹配N和D,然后使用A的正常匹配。
不确定Java语法背后的正面外观,但有关Java regex with look behind
的文章答案 3 :(得分:0)
我知道你要求正则表达式,但为什么你甚至需要一个正则表达式呢?怎么样:
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();
您可能会发现this post很有趣。当然,上面的代码假定字符串中至少有一个数字 - 最后一个数字后面的所有字符都被转换为空格。如果没有数字,则每个字符都转换为空格。