2012-05-02 116 views
1

在Java程序界定,我想找出这些子给定的字符串中所有出现:$$或$ \ d(符号“$”后跟一个整数)。匹配字符串中的某些关键字不是由某些字符

我的问题开始时,我增加了一个额外的限制,指出只有在匹配字符串不是由某些字符序列限制的子串的一部分发生匹配。

例如,我想忽略匹配,如果它们是由“/ {”和“/}”所包围的字符串的一部分。

以下示例将带出所有出现的$$或$ \ d,但不考虑忽略匹配的附加约束(如果它位于“/ {”和“/}”内部)。

public static final String PARAMETERS_PREFIX = "$"; 
public static final String ALL_PARAMS_SUFFIX = "$"; 
public static final String BEGIN_JAVA_EXPRESSION = "/{"; 
public static final String END_JAVA_EXPRESSION = "/}"; 
... 
String test = "$1 xxx $$ " //$1 and $$ are matches 
    + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match 
Set<String> symbolsSet = new LinkedHashSet<String>(); 
Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")"); 
Matcher findingMatcher = pattern.matcher(test); 
while(findingMatcher.find()) { 
    String match = findingMatcher.group(); 
    symbolsSet.add(match); 
} 
return new ArrayList<String>(symbolsSet); 

除了发现不能确定的子部分的关键字,我希望能够通过一定值后只更换这些关键字。 然后,在进行匹配之前删除分隔字符之间的所有内容的选项可能无济于事,因为之后我需要能够获取原始字符串,并将匹配的标记替换为某些值,并且分隔区域内的标记应该留下未经修改。 这应该很容易,如果我找到了正确的正则表达式。

是否有人可以给我一个关于如何编写正确的正则表达式这个问题的暗示?

回答

2

允许使用多于1个正则表达式吗?它可能不那么性感,但你可以用3个正则表达式很容易做到这一点。 (这些都不是实际的正则表达式的) 1.为了得到你正在寻找的字符串($$ | $ {NUM}) 2.对于 '/ {' 3.对于 '/}'

它应该是相当容易的无效面积在2和3。然后,您可以使用这些跨度,以消除1

+0

+1谢谢您的回答@ControlAltDel。然而,我忘了在问题中说,以后我需要用其他值替换匹配的字符串(我刚刚更新了它)。我认为只有一个正则表达式是理想的。不知道如何找到我使用多个正则表达式的关键字。 – Sergio

+0

我没有看到如何找到使用我建议的3个正则表达式的位置比使用1个正则表达式更复杂。但你知道你的问题比我更好... – ControlAltDel

+0

我想说的是,我正在寻找一个正则表达式,我可以使用它们来查找匹配,以及之后替换某些值的标记。所以我可以做一些像test.replaceAll(“killerRegex”,“newValue”)。 “killerRegex”将忽略周围区域的匹配。 – Sergio

0

结果匹配我不是正则表达式的专家,所以我会尝试使用计数器的数量{ }。 {平均值+1 }表示-1 如果计数器为0,那么使用正则表达式是安全的。如果计数器不是0,那么尝试正则表达式就没用了。我相信这是一个只有RegExp的解决方案,但我再次不是它的主人。

1

我建议为此使用多个正则表达式。试图一次完成 - 虽然诱人 - 似乎相当混乱。

  1. 取下字符串你的“Java表达式”:/{.*?/}
  2. 运行您对得到的字符串匹配:\$(?:\d+)?

注:我是第一个表达式懒惰,所以它假定任何/{的出现将最终跟随/}并且没有嵌套。

0

我不确定你可以用一个正则表达式来做到这一点。如果没有一个能提供这种终极正则表达式我做了一个小的解决方法:

public static final String PARAMETERS_PREFIX = "$"; 
public static final String ALL_PARAMS_SUFFIX = "$"; 
public static final String BEGIN_JAVA_EXPRESSION = "/{"; 
public static final String END_JAVA_EXPRESSION = "/}"; 

    String test = "$1 xxx $$ " //$1 and $$ are matches 
    + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match 
    Set<String> symbolsSet = new LinkedHashSet<String>(); 
    Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")"); 
    Matcher findingMatcher = pattern.matcher(test); 
    while(findingMatcher.find()) { 
     String match = findingMatcher.group(0); 
     int idx= findingMatcher.start(); 
     int bexIdx = test.lastIndexOf(BEGIN_JAVA_EXPRESSION,idx); 
     if(bexIdx!=-1){ 
      int endIdx = test.indexOf(END_JAVA_EXPRESSION,bexIdx); 
      if(endIdx<idx){ 
       symbolsSet.add(match); 
      } 
     } 
     else{ 
      symbolsSet.add(match); 
     } 
    } 
1

,你需要可使用此正则表达式来实现第一部分:

(?<!/{)\($[$|\d])(?!}/) 

因此,运行此之后,你会得到所有的小组比赛 - 从现在开始,您可以通过评估小组中的比赛并找到合适的替代品,让Java来完成艰苦的工作。

你应该能够使用反向引用以某种方式做替换位,但我想你可以弄明白。

UPDATE:

(?<!/{) - 这是一个负回顾后 - 它说:从当前位置断言,以前的字符不/{。如果这个计算结果为true,那么/ {的匹配被丢弃并且真正的匹配开始。 Lookahead/lookbehind是不参与比赛的零宽度断言。

(?!}/) - 类似地,但在另一个方向上 - 从当前位置断言下列字符不是} /。这些也不参加比赛。如果满足这些条件,那么实际上,您的匹配仍然只是断言中的文本,即$$或$ \ d。

BTW:它可能是你需要逃避一些字符 - 那些我记得是{和$以外的字符类

(?<!/\{)\(\$[$|\d])(?!}/) 

还看到: How to escape text for regular expression in Java

+0

@Sergio - 忘了解释,看看更新。 –

+0

谢谢@Joanna。前两个括号之间的“\”是错误的?我不明白你在逃避什么。 – Sergio

+0

@Sergio - 在第一个括号中,我用'\'来转义'{',否则可能被解释为这个结构的一部分,你可以用它来指定字符'{2,3}的出现次数“至少两次,最多三次 –

0

您可以使用一个模式与Lookaround

(?<!\\{[^\\}]{0,100})\\$(\\d|\\$)(?![^\\{]*\\})

  • (?<!\\{[^\\}]{0,100})组用于限制前驱值

    这使用否定向后看:{?<!X},其中X是不能在主表达式之前的正则表达式。在Java中,如果没有明显的最大长度,你不能使用负面的背负,那么你不能使用\\{.*。您可以使用Integer.MAX_VALUE,或testString.length()。另一件事:你必须检查你是否在开始符号之前找到结束符号。因此,该表达式是[^\\}]而不是.

  • \\$(\\d|\\$)主要群体寻求

    通常在这里。

  • (?![^\\{]*\\})组用于限制后值

    这种使用负先行:{?!X},其中X是一个正则表达式表达不能成功主要表达。在这里,你可以使用无固定长度。再次,你必须检查你是否找到了子串的开始符号。然后,您使用[^\\{]*而不是.*

但是,添加更多的约束会在您的正则表达式中增加更多的复杂性。


字符串测试模式:"$1 xx3x $$ /{xxx $2 xxx/} $4"