【问题标题】:R - Split character vector using regexR - 使用正则表达式拆分字符向量
【发布时间】:2017-10-24 15:46:36
【问题描述】:

我有一些我想阅读和分析的日志文件。不幸的是,这些文件以一种非常“丑陋”的方式保存(中间有很多特殊字符),所以我不能只阅读每一行都是一个条目的行。分隔不同条目的唯一方法是使用正则表达式,因为每个条目的开头都遵循指定的模式。

我的第一种方法是识别字符向量中的模式(我使用 readr-package 中的 read_file),并使用相应的位置通过 strsplit 拆分向量。不幸的是,位置似乎并不总是匹配,因为结果并不总是对应于条目(我猜特殊字符有问题)。

文件的典型行如下所示:

2017 年 16 月 10 日,21:51 - 乔治:这是一个典型的条目

对应的正则表达式如下:

([[:digit:]]{2})/([[:digit:]]{2})/([[:digit:]]{4}), ([[:digit:]]{2}):([[:digit:]]{2}) - ([[:alpha:]]+):

我想要的第一件事是一个 data.frame,其中每一行对应一个特定的条目(在下一步中,我会将模式分成不同的部分)。

到目前为止,我尝试了以下内容:

regex.log = "([[:digit:]]{2})/([[:digit:]]{2})/([[:digit:]]{4}), ([[:digit:]]{2}):([[:digit:]]{2}) - ([[:alpha:]]+):"
log.regex = gregexpr(regex.log, file.log)[[1]]
log.splitted = substring(file.log, log.regex, log.regex[2:355]-1)

可以看出,这个日志文件有 355 个条目。第一个被正确分开。如何在不丢失正则表达式/模式信息的情况下使用正则表达式分隔字符向量?

【问题讨论】:

  • 我想你想使用grepl(regex.log, file.log) 的组合来识别匹配的行和gsub(regex.log,"", file.log) 来提取文本。

标签: r regex string logfile


【解决方案1】:

使用捕获组和非捕获组来确定要保留的部分,并确保使用锚点:

file.log  =  "16/10/2017, 21:51 - George: This is a typical entry here"
regex.log = "^((?:[[:digit:]]{2})\\/(?:[[:digit:]]{2})\\/(?:[[:digit:]]{4}), (?:[[:digit:]]{2}):(?:[[:digit:]]{2}) - (?:[[:alpha:]]+)): (.*)$"

gsub(regex.log,"\\1",file.log)
>> "16/10/2017, 21:51 - George"
gsub(regex.log,"\\2",file.log)
>> "This is a typical entry here"

【讨论】:

  • 感谢您的回答。您能否解释一下您在正则表达式中所做的更改?
  • 我建议使用 [regex101.com] 来理解正则表达式。这可能是最好的解释(不要忘记将双斜杠 "\\" 转换为单斜杠 "\",因为双斜杠只是用于将带有单斜杠的字符串传递到 R 中。简而言之,我让你的组 @987654324 @ 到非捕获组(?:blah blah blah),然后将我想要的表达式的两个部分包装到它们自己的组中,以便它们可以在替换表达式中使用("\\1"
  • 谢谢。您的代码有效,但不幸的是它不适用于我拥有的文件。我目前正在尝试找出问题所在。
  • 您的正则表达式版本有点问题。最后的部分匹配字符向量的其余部分(以及第一个之后的所有条目)。使用它我必须对整个字符串使用递归(这将非常低效)。编辑:对不起,我想我忘了提到整个日志文件只是一个非常长的字符向量。
  • 我强烈考虑将 (A) 将文件拆分为每个元素都是记录的向量和 (B) 解析各个记录的过程分开。此答案仅解析单个记录(一个向量)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2017-02-23
相关资源
最近更新 更多