现在我们回头看看本节最开始遇到的那个问题。解决方法和水果例子完全相同,找到

模式,然后分组。

首先,看一下原始数据中典型的一行:

2014-02-01,09:20:29,Ken,James,Hey, how are you?

显然,每一行都具有相同的格式,也就是日期、时间、发送者、接收者、信息,并且

用逗号隔开。唯一特殊的是逗号可能出现在信息中,而我们不希望代码把信息中的逗号解

释为分隔符。

注意到,和前面的例子一样,正则表达式可以完美地达成这个目标。想要表达相同模

式下的一个或更多符号,只需在识别模式后面加上一个加号(+)。举个例子:"\d+"表示

一个字符串中包含一个或者更多“0”到“9”之间的数字字符。例如“1”、“23”、“456”

都匹配这个模式,而“word”不符合。在某些情况中,一个模式可能出现,也可能完全不

出现。那么我们需要将*放在识别模式符号后面,以标记这个特殊模式可能出现一次或更多

次,或者完全不出现,从而匹配更大范围的文本。

言归正传,我们需要在典型行中识别出一个足够一般的模式。我们想出如下分组模式:

(\d+-\d+-\d+),(\d+:\d+:\d+),(\w+),(\w+),\s*(.+)

现在,我们使用 readLines( )导入原始数据,就像在水果例子中所做的那样:

messages <- readLines("data/messages.txt")

然后,找出能够表达目标文本和信息的模式:

pattern <- "^(\\d+-\\d+-\\d+),(\\d+:\\d+:\\d+),(\\w+),(\\w+),\\s*(.+)$"

matches <- str_ _match(messages, pattern)

messages_df <- data.frame(matches[, -1])

colnames(messages_df) <- c("Date", "Time", "Sender", "Receiver", "Message")

这个模式看起来像一些密码。别担心,这就是正则表达式,而且如果你完成了前面的

例子,就会对它的含义有所理解。

正则表达式完美地完成了任务。message_df 文件的结构如下:

messages_df

## Date Time Sender Receiver Message

## 1 2014-02-01 09:20:25 James Ken Hey, Ken!

## 2 2014-02-01 09:20:29 Ken James Hey, how are you?

## 3 2014-02-01 09:20:41 James Ken I'm ok, what about you?

## 4 2014-02-01 09:21:03 Ken James I'm feeling excited!

## 5 2014-02-01 09:21:26 James Ken What happens?

我们使用的模式就像一把钥匙。任何正则表达式应用中最难的部分就是寻找这把钥匙。

一旦得到了它,就能够打开那道门,并从混乱的文本中尽可能多地提取需要的信息。一般

来说,寻找钥匙的难度很大程度上依赖于正例和反例的差异大小。如果差异足够明显,那

么少量符号就可以解决问题。如果差异很微小,又有许多特殊情况,如同现实世界中的大

多数问题,此时,需要更多的经验,努力思考并多次尝试,最终找到解决方法。

通过前面的例子,你应该已经领会了正则表达式的思想。其实,不需要深入地理解它是如

何工作的,但熟悉相关的函数,不论是内置函数,还是特定包内的函数,都是百利而无一害的。

如果想要深入学习,RegexOne (http://regexone.com/)是一个非常好的交互式基础学习场

所。想要学习更多特定案例和完整的识别符号,这个网页(http://www.regular-expressions.info/)

是一个很好的参考。想要寻找解决问题的好模式,可以浏览RegExr (http://www.regexr.com/)

在线交互式地测试不同的模式。