Java 使用正则表达式读取聊天信息
我使用Java中的正则表达式从文本文件中读取消息内容,其中每个对话的格式如下: 2016年5月2日,上午12:05-+910058000000:你好 2016年5月2日,上午12:06-罗斯·克拉克: 你好 我形成了以下模式:Java 使用正则表达式读取聊天信息,java,regex,Java,Regex,我使用Java中的正则表达式从文本文件中读取消息内容,其中每个对话的格式如下: 2016年5月2日,上午12:05-+910058000000:你好 2016年5月2日,上午12:06-罗斯·克拉克: 你好 我形成了以下模式: \d\d/\d\d/\d\d\d{1,2}:\d\d(\s\w\w)?\s-\s((\w+\s?\w+)|(\+\d{2}\s\d{5}\s\d{5})):(((.*)(\n)*(.*)+ 问题是,输出显示了具有发件人名称的聊天,例如,在上面的聊天示例中,“Ross
\d\d/\d\d/\d\d\d{1,2}:\d\d(\s\w\w)?\s-\s((\w+\s?\w+)|(\+\d{2}\s\d{5}\s\d{5})):(((.*)(\n)*(.*)+
问题是,输出显示了具有发件人名称的聊天,例如,在上面的聊天示例中,“Ross Clark”发送的消息是匹配的,但编号为:+91 00580 00000的消息不匹配。然而,也有一些罕见的情况下,一些消息与数字匹配
请帮帮我,我是新手
编辑:我想知道发件人何时是姓名或号码,也就是说,我想让一个组捕捉到姓名,另一个组捕捉到号码,这样我就可以进行区分。如果您知道邮件的格式及其类似内容:
<Date>, <Time> - <NameOrNumber>: <Message>
,-:
然后,您可以在-
和:
之间搜索文本
\d\d\/\d\d\/\d\d\s\d{1,2}:\d\d(\s\w\w)\s-\s(+?):((.*)(\n)*(.*)+
在这种情况下,第二组将具有名称或电话号码
请注意,date
的前斜杠在此版本中转义,因此您可能需要更改它
版本2
:.+?-\s(+?):
搜索介于-
和之间的文本:
第一组将保存名称或电话号码。假设采用上述消息格式
版本2+
:[^-]+-\s([^:]+):
搜索介于-
和之间的文本:
第一组将保存名称或电话号码。假设采用上述消息格式
版本3
:.+?-\s(+?):(.+)
第一组
-名称或编号
第二组
-消息
版本3+
:[^-]+-\s([^:]+):(.+)
第一组
-名称或编号
第二组
-消息
版本4,假设数字以+
开头,而名称不以
:[^-]+-\s([^:\+]*)(\+*[^::]+):(.+)
- 第一组保存
名称
(如果有)
- 第二组持有以
+
开头的编号(如有)
- 第三组保存
消息
版本5-消息的多行支持(基于日期的分隔符)
(\d{2}\/\d{2}\/\d{2}),\s([^-]+)+-\s([^:\+]*)(\+*[^:::]+):((.\n(?!\d{2}\/\d{2}\/\d{2},[^-]+)+)
- 第一组举行这一天
- 第二组举行时间
- 第三组持有
名称
(如有)
- 第四组持有以
+
开头的编号(如有)
- 第五组持有
信息
- 第6组保存分隔符后的字符
版本5是如何工作的?
(\d{2}\/\d{2}\/\d{2})
查找dd\mm\yy
格式
,\s([^-]+)+-\s
查找应该在,
之后和-
之前的时间
([^:\+]*)(\+*[^:]+):
在下一个:
之前查找文本。如果有+
,那么如果没有,那么它就是一个数字,而不是一个名称
((.|\n(?!\d{2}\/\d{2}\/\d{2},[^-]+)+)
-棘手的部分。这是一个棘手的问题,因为
查找除新行之外的任何字符。那么这部分做什么呢?它搜索任何未后跟dd\mm\yy,-
的字符或\n
。简单地说,如果新行
以日期开始,它不会将其作为消息的一部分捕获
笔记
\d{2}\/\d{2}\/\d{2}
允许像99/99/99
这样的非法日期。可以防止它,但它的解决方案是一个非常大的正则表达式
,\s([^-]+)+-\s
-此搜索时间假定介于,
和-
之间。这可以根据实际需要更仔细地完成。好的。让我们使用regex101进行以下操作:
我使用的模式是:
(\d{2}\/\d{2}\/\d{2}),\s(\d{1,2}:\d{2}(?:\s(?:AM|PM)))?\s-\s(.*):\s(.*)
这是什么意思?Regex101对此进行了详细解释,但让我简要强调一下这些更改。简单地说,使用*
作为名称和消息。它代表“任意字符,从零到任意多”。您可以将其更改为+
,以确保名称或消息不能为空(如果是这种情况)
我用\d{2}
缩写了你的\d\d
东西,这是一样的。另外,as/
是正则表达式中具有特殊含义的字符;如果您只想匹配字符本身,则需要通过在其前面添加一个\
来对其进行转义。在Java中,这个转义字符本身有一个特殊的含义(即转义Java字符串中的内容)。因此,您需要在Java中转义转义字符。这导致,例如,\\/
但是我们如何在Java本身中实现这一点呢?下面是一些代码:
Pattern pattern = Pattern.compile("(\\d{2}\\/\\d{2}\\/\\d{2}),\\s(\\d{1,2}:\\d{2}(?:\\s(?:AM|PM)))?\\s-\\s(.*):\\s(.*)");
Matcher matcher = pattern.match(inputText);
if (matcher.find()) {
String date = matcher.group(1);
String time = matcher.group(2);
String name = matcher.group(3);
String message = matcher.group(4);
// Do something with this
}
还有一件事:(…)
是一个捕获组。您可以使用matcher.group(X)
访问匹配的内容。如果您想在不使用捕获组的情况下使用(…)
,您可以使用(?:…)
,就像我对AM、PM之类的东西所做的那样
希望你能理解一切,玩得开心。以下是模式文档:这将所有主要组件分为不同的捕获组:
(\d{2}\/\d{2}\/\d{2}),\s(\d{2}:\d{2}\s(?:AM | PM))\s-\s(.*):\s(.*)
第一组:年月日
第2组:HH:MM上午/下午
第3组:发件人的姓名或号码
第4组:在您的示例中,第3组消息的内容与(AM | PM)
相匹配。您可以将其更改为(?:AM | PM)
,以表示不可用