1. 概述

有时我们需要在字符串中查找数字或完整数字。我们可以使用正则表达式或某些库函数来做到这一点。

在本文中,我们将 使用正则表达式来查找和提取字符串中的数字 。我们还将介绍一些计算数字的方法。

2. 计算数字

让我们首先计算字符串中找到的数字。

2.1.使用正则表达式

我们可以使用Java 正则表达式计算数字的匹配数量

在正则表达式中, “*\d ”* 匹配“任何单个数字”**。让我们使用这个表达式来计算字符串中的数字:

int countDigits(String stringToSearch) {
    Pattern digitRegex = Pattern.compile("\\d");
    Matcher countEmailMatcher = digitRegex.matcher(stringToSearch);

    int count = 0;
    while (countEmailMatcher.find()) {
        count++;
    }

    return count;
}

一旦我们为正则表达式定义了 匹配器 ,我们就可以在循环中使用它来 查找 和计算所有匹配项。我们来测试一下:

int count = countDigits("64x6xxxxx453xxxxx9xx038x68xxxxxx95786xxx7986");

assertThat(count, equalTo(21));

2.2.使用 Google Guava CharMatcher

要使用Guava ,我们首先需要添加 Maven 依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

Guava 提供了 CharMatcher.inRange​ 方法 来计算数字:

int count = CharMatcher.inRange('0', '9')
  .countIn("64x6xxxxx453xxxxx9xx038x68xxxxxx95786xxx7986");

assertThat(count, equalTo(21));

3. 寻找数字

计算数字需要捕获有效数字表达式的所有数字的模式。

3.1.寻找整数

要构造一个表达式来识别整数,我们必须考虑 它们可以是正数或负数,并且由一个或多个数字的序列组成 。我们还注意到负整数前面有一个减号。

因此,我们可以通过将正则表达式扩展为“ -?\d+ ”来查找整数。该模式的意思是“一个可选的减号,后跟一个或多个数字”。

让我们创建一个示例方法,使用此正则表达式查找字符串中的整数:

List<String> findIntegers(String stringToSearch) {
    Pattern integerPattern = Pattern.compile("-?\\d+");
    Matcher matcher = integerPattern.matcher(stringToSearch);

    List<String> integerList = new ArrayList<>();
    while (matcher.find()) {
        integerList.add(matcher.group());
    }

    return integerList;
}

一旦我们在正则表达式上创建了 匹配器 ,我们就可以在循环中使用它来 查找 字符串中的所有整数。我们在每场比赛中调用 group 来获取所有整数。

让我们测试一下 findIntegers

List<String> integersFound = 
  findIntegers("646xxxx4-53xxx34xxxxxxxxx-35x45x9xx3868xxxxxx-95786xxx79-86");

assertThat(integersFound)
  .containsExactly("646", "4", "-53", "34", "-35", "45", "9", "3868", "-95786", "79", "-86");

3.2.求小数

要创建一个查找十进制数字的正则表达式,我们需要考虑编写它们时使用的字符模式。

如果十进制数为负数,则以减号开头。后面跟着一个或多个数字以及可选的小数部分。该小数部分以小数点开头,后面是另一个由一个或多个数字组成的序列。

我们可以使用正则表达式 “-?\d+(\.\d+)?”来 定义它。 “:

List<String> findDecimalNums(String stringToSearch) {
    Pattern decimalNumPattern = Pattern.compile("-?\\d+(\\.\\d+)?");
    Matcher matcher = decimalNumPattern.matcher(stringToSearch);

    List<String> decimalNumList = new ArrayList<>();
    while (matcher.find()) {
        decimalNumList.add(matcher.group());
    }

    return decimalNumList;
}

现在我们将测试 findDecimalNums

List<String> decimalNumsFound = 
  findDecimalNums("x7854.455xxxxxxxxxxxx-3x-553.00x53xxxxxxxxxxxxx3456xxxxxxxx3567.4xxxxx");

assertThat(decimalNumsFound)
  .containsExactly("7854.455", "-3", "-553.00", "53", "3456", "3567.4");

4. 将找到的字符串转换为数值

我们可能还希望将找到的数字转换为其 Java 类型。

让我们使用 映射将整数转换为 Long

LongStream integerValuesFound = findIntegers("x7854x455xxxxxxxxxxxx-3xxxxxx34x56")
  .stream()
  .mapToLong(Long::valueOf);
        
assertThat(integerValuesFound)
  .containsExactly(7854L, 455L, -3L, 34L, 56L);

接下来,我们将以同样的方式将十进制数转换为 Double

DoubleStream decimalNumValuesFound = findDecimalNums("x7854.455xxxxxxxxxxxx-3xxxxxx34.56")
  .stream()
  .mapToDouble(Double::valueOf);

assertThat(decimalNumValuesFound)
  .containsExactly(7854.455, -3.0, 34.56);

5. 查找其他类型的数字

数字可以用其他格式表示,我们可以通过调整正则表达式来检测。

5.1.科学计数法

让我们找到一些使用科学记数法格式化的数字:

String strToSearch = "xx1.25E-3xxx2e109xxx-70.96E+105xxxx-8.7312E-102xx919.3822e+31xxx";

Matcher matcher = Pattern.compile("-?\\d+(\\.\\d+)?[eE][+-]?\\d+")
  .matcher(strToSearch);

// loop over the matcher

assertThat(sciNotationNums)
  .containsExactly("1.25E-3", "2e109", "-70.96E+105", "-8.7312E-102", "919.3822e+31");

5.2.十六进制

现在我们将在字符串中查找十六进制数字:

String strToSearch = "xaF851Bxxx-3f6Cxx-2Ad9eExx70ae19xxx";

Matcher matcher = Pattern.compile("-?[0-9a-fA-F]+")
  .matcher(strToSearch);

// loop over the matcher

assertThat(hexNums)
  .containsExactly("aF851B", "-3f6C", "-2Ad9eE", "70ae19");

六,结论

在本文中,我们首先讨论了如何使用正则表达式和 Google Guava 的 CharMatcher 类来计算字符串中的数字。

然后,我们探索使用正则表达式来查找整数和小数。

最后,我们介绍了如何查找其他格式的数字,例如科学记数法和十六进制。

与往常一样,本教程的源代码可以在 GitHub 上找到。