Java 正则表达式:忽略组的顺序
我有一段文字: 随机文本1150,25美元随机文本 还有一个简单的正则表达式,用于提取不同货币的金额:Java 正则表达式:忽略组的顺序,java,regex,Java,Regex,我有一段文字: 随机文本1150,25美元随机文本 还有一个简单的正则表达式,用于提取不同货币的金额: (((\d+)(,?\s?)(\d{1,2}))\s?(印尼国家电力公司欧元美元瑞士法郎英镑) 这就给了我这些群体: 1150,25美元 1150,25 1150 , 二十五 美元 但是,数字和货币可以互换其头寸: 随机文本1150美元,25随机文本 或 随机文本1150美元,25随机文本 如何改进正则表达式以满足该条件,而不重复整个组(AB | BA),同时保持当前分组?您可以使用这种模式:
(((\d+)(,?\s?)(\d{1,2}))\s?(印尼国家电力公司欧元美元瑞士法郎英镑)
这就给了我这些群体:
如何改进正则表达式以满足该条件,而不重复整个组(AB | BA),同时保持当前分组?您可以使用这种模式:
String p = "\\b (?=[\\dPEUCG]) # to jump quickly at interesting positions \n" +
"(?= # open a lookahead \n" +
" (?> [\\d,]+ \\s* )? # perhaps the value is before \n" +
" (?<currency> PLN|EUR|USD|CHF|GBP ) # capture the currency \n" +
" (?:\\b|\\d) # a word boundary or a digit \n" +
") # close the lookahead \n" +
"(?> [B-HLNPRSU]{3} \\s* )? (?<value> \\d+(?:,\\d+)? ) ";
Pattern RegComp = Pattern.compile(p, Pattern.COMMENTS);
String s = "USD 1150,25 randomtext \n" +
"Non works randomtext 1150,25 USD randomtext\n" +
"Works randomtextUSD 1150,25 USD randomtext\n" +
"Works randomtext USD 1150,25 randomtext\n" +
"Works randomtext USD1150,25 randomtext\n" +
"Non work randomtext 1150,25 USD randomtext";
Matcher m = RegComp.matcher(s);
while( m.find() ) {
System.out.println(m.group("value") + " : " + m.group("currency"));
}
String p=“\\b(?=[\\dPEUCG])#在感兴趣的位置快速跳转\n”+
“(?=#打开前瞻\n”+
(?>[\\d,]+\\s*)?#可能值在\n之前+
“(?兹罗提|欧元|美元|瑞士法郎|英镑)#捕获货币\n”+
(?:\\b |\\d)#字边界或数字\n+
“)#关闭前瞻\n”+
“(?>[B-HLNPRSU]{3}\\s*)?(?\\d+(?:,\\d+)”;
Pattern RegComp=Pattern.compile(p,Pattern.COMMENTS);
字符串s=“USD 1150,25随机文本\n”+
“非作品随机文本1150,25美元随机文本\n”+
“作品随机文本1150美元,25美元随机文本\n”+
“作品随机文本1150.25美元随机文本\n”+
“Works randomtext USD1150,25 randomtext\n”+
“非工作随机文本1150,25美元随机文本”;
匹配器m=注册表匹配器;
while(m.find()){
System.out.println(m.group(“value”)+:“+m.group(“currency”));
}
其思想是在前瞻(即零宽度断言)中捕获货币。lookahead只是一个断言,不使用字符,其中的子模式描述了之前的最终值。因此,货币的位置不会改变任何东西。
该值是在前瞻之外捕获的
关于\\b(?=[\\dPEUCG])
:
此子模式的目标是过滤字符串中不是以数字或不同货币的前一个字母开头的单词的开头的位置,而无需测试整个模式。它不太优雅,但您也可以通过以下方法实现:
(?<!\d|\d,)(?=(?:[\d,]+\s)*(PLN|EUR|USD|CHF|GBP)(?:\s*[\d,]+\s)*)(?=(?:PLN|EUR|USD|CHF|GBP)*\s*((\d+)(,?\s?|.)(\d{1,2}))\s?(?:PLN|EUR|USD|CHF|GBP)*)[\d,\sPLNEURUSDCHFGB]+(?=\b\s)
(?
但是,如果您不需要匹配此部分(例如替换等),只需捕获字符串的相关部分,就可以使用:
(?<!\d|\d,)(?=(?:[\d,]+\s)*(PLN|EUR|USD|CHF|GBP)(?:\s*[\d,]+\s)*)(?=(?:PLN|EUR|USD|CHF|GBP)*\s*((\d+)(,?\s?|.)(\d{1,2}))\s?(?:PLN|EUR|USD|CHF|GBP)*)
(?
它用于预测未来:
(?=(?:[\d,]+\s)*(兹罗提|欧元|美元|瑞士法郎|英镑)(?:\s*[\d,]+\s)*)
-货币
前面或后面有数字
(?=((?:PLN |欧元|美元|瑞士法郎|英镑)*\s*(\d+,?\s |)(\d{1,2})(?:\s*(?:PLN |欧元|美元|瑞士法郎|英镑))
- 前面或后面跟货币的数字
以编程方式构造regexp:
BigDecimal amount = null;
String currency = null;
String currencyRegex = "(PLN|EUR|USD|CHF|GBP)";
String amountRegex = "(\\d+)(?:,?\\s?|.)(\\d{1,2})";
Pattern currencyAmountPattern = Pattern.compile(
currencyRegex + "\\s?" + amountRegex
+ "|"
+ amountRegex + "\\s?" + currencyRegex);
Matcher matcher = currencyAmountPattern.matcher(input);
if (matcher.find()) {
if (matcher.group(1) != null) {
currency = matcher.group(1);
amount = new BigDecimal(matcher.group(2) + "." + matcher.group(3));
} else {
currency = matcher.group(6);
amount = new BigDecimal(matcher.group(4) + "." + matcher.group(5));
}
}
不幸的是,不能使用命名组,我错了。要使用命名组作为反向引用,该组必须预先存在。看到您使用的语言了吗?@casimirithippolyte Java。添加到标记中。是否会出现随机文本在货币之前包含数字的情况?例如,blah 123 USD 123 blah
?@Sanchi这不是一个好问题,但不,它不会发生。在这一点上,为了理智起见,我们可能只需要使用多个正则表达式,或者完全远离它们。