【发布时间】:2016-02-14 21:56:36
【问题描述】:
我必须从字符串文本中提取度量单位和数量。就像在这个示例中一样:
Original String // result:
abc1mgabc // extract 1 and mg separately
abc100mlabc //100 and ml
abc256kgabc //256 and kg
直到现在我第一次使用这个正则表达式:
(?i)\d{1,5}(mg|g|gr|kg|ml|l)
提取数量和单位并存储到quant_unit字符串中。
之后,我应用quant_unit 这两个正则表达式:\d 和(?i)(mg|g|gr|kg|ml|l) 分别提取“数量”和“测量单位”。
但我认为它必须有一种方法可以通过在原始字符串上仅应用正则表达式(对于要提取的每个项目)来单独提取它?
我虽然使用了一些类似的东西:
original_string -> applyRegex(提取度量和单位)-> applyRegex2(从中提取度量或单位)。
使用它自己的正则表达式或 Java 中的 Pattern 类。
我正在创建一个枚举来轻松访问模式:
public enum Patterns {
//the expression is: (?i)\d{1,5}(mg|g|gr|kg|ml|l)
QUANTITY_UNIT("(?i)\\d{1,5}(" + MeasureUnit.getRegex() + ")"),
QUANTITY("\\d"),
UNIT("(?i)(" + MeasureUnit.getRegex() + ")");
private Pattern pattern;
Patterns(String patternString) {
System.out.println(patternString);
pattern = pattern.compile(patternString);
}
public Pattern getPattern() {
return pattern;
}
public Matcher getMatcher(CharSequence input) {
return getPattern().matcher(input);
}
public String findGroup(CharSequence input) {
Matcher matcher = getMatcher(input);
matcher.find();
return matcher.group();
}
以及所需行为的单元测试:
public class PatternsTest {
@Test
public void quantityUnit() {
String testString = "abc1kgabc1l";
String fg = Patterns.QUANTITY_UNIT.findGroup(testString);
Assert.assertEquals("1KG", fg);
}
@Test
public void quantity() {
String testString = "abc1kgabc1l";
String fg = Patterns.QUANTITY.findGroup(testString);
Assert.assertEquals("1", fg);
}
@Test
public void unity() {
String testString = "abc1kgabc1l";
String fg = Patterns.UNIT.findGroup(testString);
Assert.assertEquals("kg", fg);
}
}
编辑
我根据评论和答案做了一些重构,现在可以正常工作了:
public enum Patterns {
QUANTITY_UNIT("(?i)([0-9]+)(" + MeasureUnit.getRegex() + ")");
private Pattern pattern;
Patterns(String patternString) {
pattern = pattern.compile(patternString);
}
public Pattern getPattern() {
return pattern;
}
public Matcher getMatcher(CharSequence input) {
return getPattern().matcher(input);
}
public String getQuantity(CharSequence input) {
final int group_idx = 1;
Matcher matcher = getMatcher(input);
boolean found = matcher.find();
return found ? toLower(matcher.group(group_idx)) : "";
}
private String toLower(String input) {
return input.toLowerCase();
}
public String getUnity(CharSequence input) {
final int group_idx = 2;
Matcher matcher = getMatcher(input);
boolean found = matcher.find();
return found ? toLower(matcher.group(group_idx)) : "";
}
}
测试:
public class MeasureUnityTest {
@Test
public void quantity() {
String testString = "abc1kgabc1l";
String fg = QUANTITY_UNIT.getQuantity(testString);
Assert.assertEquals("1", fg);
}
@Test
public void unity() {
String testString = "abc1kgabc1l";
String fg = QUANTITY_UNIT.getUnity(testString);
Assert.assertEquals("kg", fg);
}
@Test
public void unityUpperCase() {
String testString = "abc1KGabc1l";
String fg = QUANTITY_UNIT.getUnity(testString);
Assert.assertEquals("kg", fg);
}
@Test
public void unityNoOccurrence() {
String testString = "fasfasfasfaf";
String fg = QUANTITY_UNIT.getQuantity(testString);
Assert.assertEquals("", fg);
}
@Test
public void unityEmptyString() {
String testString = "";
String fg = QUANTITY_UNIT.getQuantity(testString);
Assert.assertEquals("", fg);
}
/* If more than one matches, return the first*/
@Test
public void unityMoreThanOne() {
String testString = "abc5mlabc5kg";
String fg = QUANTITY_UNIT.getUnity(testString);
Assert.assertEquals("ml", fg);
}
/* If more than one matches, return the first*/
@Test
public void quantityMoreThanOne() {
String testString = "abcm5mlabc1kg";
String fg = QUANTITY_UNIT.getQuantity(testString);
Assert.assertEquals("5", fg);
}
}
【问题讨论】:
标签: java regex pattern-matching