【问题标题】:How to change regex pattern so that it finds each match sequentially如何更改正则表达式模式,以便它按顺序找到每个匹配项
【发布时间】:2013-03-30 21:14:00
【问题描述】:

我有一个文本文件,我在其中使用以下语法存储证书:

-----BEGIN CERTIFICATE-----
Certificate is in here.  It's a really long string of characters and looks like garbage.  Each certificate is variable length.
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
Another certificate is in here
-----END CERTIFICATE-----

然后,我有代码尝试读取上述文本文件,并一一检查每个证书。

//This copies all of my certificates from a file into a String
String certificates = new Scanner(new File("certificates.txt"), "UTF-8").useDelimiter("\\A").next();

//This creates a pattern so that I can examine each certificate one at a time
//(?s) allows this pattern to span several lines.
Pattern pattern = Pattern.compile("(?s)-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE");

Matcher matcher = pattern.matcher(certificates);

//I attempt to examine each certificate one at a time
while(matcher.find())
{
    System.out.println(matcher.group());
}

但是,当我调用 matcher.find() 时,它会返回 整个 证书文件。我想是因为它在文件开头找到“-----BEGIN CERTIFICATE-----”,然后在文件末尾找到“-----END CERTIFICATE-----” .

如何更改我的正则表达式模式,以便它按顺序找到每个证书?

【问题讨论】:

  • 您是否尝试过像这样使用非贪婪的.*:.*??
  • @Jerry, .*? 成功了。谢谢!

标签: java regex


【解决方案1】:

原因是.* 是一个greedy 表达式,它匹配尽可能多的证书部分。您可以通过添加? 量词使用不情愿的表达式将此匹配限制为单个部分:

Pattern pattern = 
   Pattern.compile("(?s)-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE");

【讨论】:

    【解决方案2】:

    如果你使用下面的例子:

    -----BEGIN CERTIFICATE-----
    asAasdfO'Psadf-ASDFgrvd-dK;9twqegvb5wetg5089'O0'[U'P4we5AASDSFDevbF54wgwe54-t4g5g54wgsefe4-
    -----END CERTIFICATE-----
    

    那么下面的正则表达式需要242个步骤来拉取,如果证书更长会快速增长:

    (?s)-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE
    

    242 并不多,但话又说回来,这是一个非常小的证书。我见过证书变得很长。我不确定这种影响是否会对你造成太大伤害。但是,下面的正则表达式只需要 72 步,无论证书有多长,总是大约 72 步:

    (-{5})BEGIN\sCERTIFICATE\1\s*(?<Cert>[^-]*(?:(?=\1)|-))*?\s*\1END\sCERTIFICATE\1
    

    它可能看起来更复杂。但是说Regex的时候,就很清楚了。此外,它不会包括 Begin 之后和 End 之前的换行符。只需拉出 Matcher.Group("Cert") 即可提取证书。

    细分: 首先,匹配五个破折号。将其设置为 Capture Group 1 以便以后使用。 匹配“开始证书”。正则表达式中的空格很难看,应该是 [ ] 或 \s。 用 \s(5 个破折号)调用 Capture Group 1。 修剪空格,包括带有 \s* 的换行符 在 Cert Group 中,一次捕获所有文本集(不要懒惰),直到后面跟着五个破折号。 (这是递归的)。 匹配任何空格(包括换行符)、五个破折号、END CERTIFICATE 和五个破折号。

    【讨论】:

    • 这太棒了。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-06-17
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多