如何使用正则表达式提取特定字符串的部分?

时间:2013-07-03 13:59:24

标签: java regex

我正在尝试从此链接http://osherove.com/tdd-kata-1/解决以下针对测试驱动开发的练习,并且我已经接近要求的末尾。

我总是害怕正则表达式,但似乎我必须学习它们。无论如何,我正在尝试执行以下操作: - 取一个字符串,从中提取数字并求它们。困扰我的要求是那个

  

允许多个这样的分隔符:“// [delim1] [delim2] \ n”例如“// [*] [%] \ n1 * 2%3”应该返回6.确保你也可以处理多个长度超过一个字符的分隔符。

该要求意味着我必须从以delim1开头并以新行符号delim2结尾的字符串中提取//\n等。然后我需要使用这些分隔符并在\n之后提取数字。每个分隔符都用方括号括起来。

现在,我如何在带有正则表达式的java中做到这一点?

到目前为止我所拥有的是以下代码,其中涵盖了上述链接中的要求:

import java.util.ArrayList;

public class Calculator {

    public String getDelimiter(String input) {
        String delimiter = "";
        String changeDelimiter = input.split("\\n")[0];
        delimiter = changeDelimiter.substring(2);
        return delimiter;
    }

    public int calculate(String input) {
        String[] numbers;

        if (input.contains("//")) {
            String delimiter = getDelimiter(input);
            System.out.println("aaaaaaaaaaaaaaaaaaaaaaa : " + delimiter); //testing the value
            String calculation = input.split("\\n")[1];
            numbers = calculation.split("[" + delimiter + "]+");
            System.out.println("bbbbbbbbbbbbbbbbbbbbbbbb"); //testing the values
            for (String number : numbers) {
                System.out.print(number + ":");
                // System.out.print(Integer.parseInt(number) + " ");
            }

        } else
            numbers = input.split(",|\\n");

        if (input.isEmpty()) {
            return 0;
        }
        if (input.length() == 1) {
            return Integer.parseInt(input);
        }
        else {
            return getSum(numbers);
        }
    }

    private int getSum(String[] numbers) throws IllegalArgumentException {
        int sum = 0;
        ArrayList<Integer> negatives = new ArrayList<Integer>();
        for (int i = 0; i < numbers.length; i++) {
            if (Integer.parseInt(numbers[i]) < 0) {
                negatives.add(Integer.parseInt(numbers[i]));
            }
            if (Integer.parseInt(numbers[i]) >= 1000) {
                continue;
            } else
                sum += Integer.parseInt(numbers[i]);
        }
        if (negatives.isEmpty()) {
            return sum;
        } else {
            String negativeNumbers = "";
            for (Integer number : negatives) {
                negativeNumbers += number.toString() + " ";
            }
            throw new IllegalArgumentException("Negatives not allowed : " + negativeNumbers);
        }

    }

}

2 个答案:

答案 0 :(得分:0)

您可以使用正则表达式

\d匹配一位数

+是一个量词,它匹配先前的模式1到很多次

所以\d+会匹配1到多个数字


您的代码将是

public int addAllInts(String s)
{
    int temp=0;
    Matcher m=Pattern.compile("\\d+").matcher();
    while(m.find())
    {
        temp+=Integer.parseInt(m.group());
    }
    return temp;
}

答案 1 :(得分:0)

这比仅匹配任何数字都要长,但它应该适用于像“delim1”这样的分隔符,即包含数字的分隔符。我试图解释内联的模式和步骤。

    final String input = "//[delim1][delim2]\n12delim125delim2";
    // split the input string so you will get anything after // and before \n
    // and anything after \n until end of line ($)
    Pattern p = Pattern.compile("^//(.+)\\n(.*)$");
    Matcher m = p.matcher(input);
    if (!m.matches()) {
      System.out.println("Input string not valid");
      return;
    }

    String delimString = m.group(1);
    String searchString = m.group(2);

    // This matches the opening square bracket,
    // then as a capturing group, anything except a closing bracket. 
    // Finally it matches the closing bracket of the delimiter definition.
    Pattern pDelim = Pattern.compile("\\[([^\\]]+)\\]");
    Matcher mDelim = pDelim.matcher(delimString);

    // build a regex for String.split in the format: delim1|delim2|delim3|...
    String delimiters = "";
    while (mDelim.find()) {
     delimiters += (Pattern.quote(mDelim.group(1)) + "|");
    }
    delimiters = delimiters.substring(0, delimiters.length()-1);

    // split string and convert numbers to integers, then sum them up
    String[] numStrings = searchString.split(delimiters);
    int sum = 0;
    for (String num : numStrings) {
      sum += Integer.parseInt(num);
    }

    System.out.println("Sum: " + sum);

编辑/更多解释

正则表达式\\[([^\\]]+)\\]包含三个部分:

  • "\\[":这将与分隔符定义的左方括号相匹配。注意两个必要的反斜杠,因为Java编译器会解释一个反斜杠。但是,我们希望匹配[,这也是正则表达式中的特殊字符。所以我们需要两个。
  • ([^\\]]+):外部括号创建一个所谓的捕获组,您可以稍后使用Matcher.group(n)进行访问,其中n是该组的索引。因此,1将是第一组定义,2是第二组,依此类推。 0返回整个匹配的字符串。

    • [^\\]]+:此正则表达式将匹配分隔符定义的内容,即方括号内的所有内容。这次,外部[]不会转义。它们具有特殊含义并定义了一个字符类。字符类将匹配其中指定的任何字符。例如[abc]匹配abc但不匹配d。字符类开头的^具有特殊含义,反转字符类。因此,[^ abc]会匹配abc之外的任何字符。

      我们的字符类中定义的唯一字符是],因此字符类将匹配除结束方括号之外的任何字符,该方括号将结束分隔符定义。附加到字符类的+表示:匹配至少1个字符或更多字符(如果可能)。

  • \\]:只需匹配方括号。

使用此正则表达式,我们通过调用Matcher.find()Matcher.group(1)来接收分隔符字符串。 String.split()也为其分隔符参数提供正则表达式。所以现在我们需要构建一个匹配任何前面解析的分隔符字符串的正则表达式。 Pattern.quote()用于转义分隔符字符串。如果分隔符包含将由正则表达式解释的特殊字符,则可能需要这样做。 |是一个特殊字符or。我们构建的整个正则表达式字符串将匹配任何分隔符字符串。因此,String.split()会将字符串拆分为分隔符。