Java 如何使用正则表达式在同一行上捕获数量可变的模式?

Java 如何使用正则表达式在同一行上捕获数量可变的模式?,java,regex,Java,Regex,所以,我被要求创建一个java文件,该文件读取字符,使用正则表达式提取信息,并打印出来以供分配。我对正则表达式不太熟悉,但我可以完成作业,假设每行只包含一个我需要的文本示例,或者不包含任何文本示例。但当我试图在同一行上收集多段文本时,问题就出现了。特别是如果行中有我不应该读的文本 比如, [这里有一行示例,我可能需要阅读example@such.com我还需要额外的用户名地址pleasehelpme@such.com看到了吗?] 如果你能用外行的语言来解释你的答案,那将大有帮助 我曾尝试查找答案

所以,我被要求创建一个java文件,该文件读取字符,使用正则表达式提取信息,并打印出来以供分配。我对正则表达式不太熟悉,但我可以完成作业,假设每行只包含一个我需要的文本示例,或者不包含任何文本示例。但当我试图在同一行上收集多段文本时,问题就出现了。特别是如果行中有我不应该读的文本

比如,

[这里有一行示例,我可能需要阅读example@such.com我还需要额外的用户名地址pleasehelpme@such.com看到了吗?]

如果你能用外行的语言来解释你的答案,那将大有帮助

我曾尝试查找答案,但我能找到的最接近答案是,一个基本正则表达式页面和一个显示扫描两种不同模式示例的网站。我只想说,我对这方面还不太熟悉,我真的需要帮助

Pattern pat = Pattern.compile("\\S*([a-zA-Z]+)@$");
    Matcher mat = pat.matcher(texttoread[i]);
        while(mat.find()) 
        {
           Holdingvar = Holdingvar + mat.group();
    }
//Keep in mind that this still needs to be loaded into an array so that I can 
//print them all out.
如前所述,如果一行只包含我想要的内容之一,或者不包含我想要的内容,那么它就可以完美地工作。在这种情况下,它会打印地址的名称


此外,它只打印出最新的地址,地址列在其中只包含一个地址的所有行之后。这是一个问题,因为我希望它们按顺序打印出来。

您的示例正则表达式使用了一个与输入结尾匹配的
$
模式。因此,它只能匹配一次。这是你试图做的一个糟糕的例子

相反,让我们保持简单:将电子邮件地址定义为符号处的
@
,前后都有文本,并将文本定义为“非空白”

正则表达式将是:
\S+@\S+

即,一个或多个“非空白”,一个
@
符号,然后是一个或多个“非空白”

此模式可以在一个字符串中匹配多次:

String input = "Here is an example line that I might have to read example@such.com and I have to extra the username addresses pleasehelpme@such.com see?";

Pattern p = Pattern.compile("\\S+@\\S+");
Matcher m = p.matcher(input);
while (m.find()) {
    System.out.println(m.group());
}
输出

example@such.com
pleasehelpme@such.com

< /代码>

根据您的情况考虑的一些选项:

  • 如果有一些您想忽略的“可选”文本,但它是一种相当固定的格式,您可以通过放置一个?在括号之后(如果不存在,当你用匹配的组号在匹配器上调用GROP()时,它会变成空的;也考虑不使用(………)来捕获它(如果你不特别需要引用它)。这通常假设您正在匹配整行,而不是使用find()提取行中的多个元素
  • 正如Andreas所提到的,您不必与行的开始/结束相匹配。默认情况下,+和*等量词是“贪婪的”:它们将匹配尽可能多的字符,前提是它们仍然允许表达式的其他部分匹配,这意味着您甚至不必总是指定“锚”(匹配之前/之后的内容),您可以使用find()迭代匹配
  • 但如有必要,您可以指定匹配之前/之后必须出现的上下文,例如,指定\b以引用“单词边界”(但请参阅模式文档以了解其具体含义)。如果您需要此选项,请查看模式中“向前看”和“向后看”规范的选项:换句话说,这使您可以选择说“查找此模式,假设该模式正好发生在它之前…”
在仍然匹配需要匹配的子字符串的情况下,尝试使模式尽可能具体是一个好主意。快速的互联网搜索将向您展示,什么是匹配电子邮件的好模式是一个复杂的问题。下面是一个非常简单的例子(实际上,可能太简单了,但重点是它比您当前使用的表达式更具体):


我明白你想做什么。但主要的问题是我必须将它们放入一个数组中。按照你的建议,这会更有效,但这是我得到的限制条件之一。@StackUndertow所以你的问题不是关于正则表达式的?您的问题是如何向数组添加值?由于您不知道会找到多少,请添加到
列表中。如果绝对需要数组,则将
列表
转换为循环后的数组。否。我知道如何向数组中添加值。问题是,我需要使用regex在同一行提取多个值,并将它们作为单独的实体放入一个数组中。此外,建议末尾的\\S+不知何故导致程序读取.com之后的文本。有没有办法调用空格或行尾?@StackUndertow将循环中找到的电子邮件添加到数组中。既然您声称知道如何添加到数组中,我看不出有什么问题“在.com之后读课文”不知道你的意思。你可以在答案的输出中清楚地看到,它停在
.com
后面的空格处,所以我不明白你为什么要问如何让它停在空白处,而它显然已经在这样做了。说实话,一些代码行以@结尾,后跟一个空格,然后是几个字符。建议的解决方案是读取那些不好的字符。我删除$时出现了一个问题,尽管我认为如果它真的表示一行的结束,那么肯定会发生这种情况(我相信你会这么说)。为什么
group(0)
而不仅仅是
group()
?哦,没有特别的原因-我想这正是我习惯键入的-它们被定义为等价的。
Pattern p = Pattern.compile("[a-zA-Z\\.]+@[a-zA-Z\\.]+\\.[a-zA-Z]+");

Matcher m = p.matcher(line);
while (m.find()) {
    System.out.println(m.group(0));
}