0

我正在与正则表达式作斗争,但我无法弄清楚。

我有一个从 last.fm (www.lastfm.com) 中提取的投标数据库。该文件是一个 .txt 文件,其中每一行的每一列都由超过 1.7 GB 的“,”(逗号)分隔,并且有一些字符弄乱了对 R 的读取。直到现在我设法理解了哪里出了问题并且主要问题来自其他引号内的“(引号)。

为了说明,这里是应用 readLines 时的 .txt 文件示例。

[1] "user,\"Method Man & Redman\",\"Da Rockwilder\",0,2012,2,10,8,0,41"       
[2] "user,\"Method Man & Redman\",\"Y.O.U.\",0,2012,2,10,7,56,25"             
[3] "user,\"Method Man & Redman\",\"Blackout\",0,2012,2,10,7,51,53"           
[4] "user,\"Chuckie\",\"Who Is Ready To Jump (Club Mix)\",0,2012,2,10,7,40,12"
[5] "user,\"Opgezwolle\",\"Volle Kracht\",0,2012,2,10,7,36,31"                
[6] "user,\"Opgezwolle\",\"Ut Is Wat Het Is\",0,2012,2,10,7,33,25"

基本上这变成了一个包含 10 列的数据框:用户名、“艺术家”、“曲目”、喜爱 (0/1)、年、月、日、小时、分钟、秒

上面的例子可以很容易地阅读而没有任何问题,但是当发生这样的事情时我会遇到问题:

[1] "user,\"Fall Out Boy\",\"\"The Take Over, The Breaks Over\"\",0,2010,4,17,7,11,37"
[2] "user,\"Gare du Nord\",\"I Want Love 12\" Remix\",0,2011,6,12,19,32,33"

在第一种情况下,由于双引号,曲目名称中的逗号将其分为两个不同的列,而不是 10 列,我得到 11 列。在第二种情况下, 12" 使字符串“打开”,直到找到类似的情况才停止。发生这种情况时,我丢失了几行数据框。

我想要什么作为解决方案?我想删除所有“(引号),除了围绕艺术家姓名和曲目名称的那些。

输出:输出将在每行中总共有四 (4) 个“(引号)。“艺术家”和“曲目名称”。因此,给我带来问题的那 2 行的输出将是:

[1] "user,\"Fall Out Boy\",\"The Take Over, The Breaks Over\",0,2010,4,17,7,11,37"
[2] "user,\"Gare du Nord\",\"I Want Love 12 Remix\",0,2011,6,12,19,32,33"

我尝试将 Regex 与 gsub 和 gstring 一起使用,但我无法让它仅提取多余的 " 标记。

如果这太复杂了,除了前 3 个(艺术家名称周围的引号和轨道名称周围的第一个引号)和最后一个(轨道名称末尾的引号)之外的所有 "的情况下(我会手动完成其余的)。我在这里假设没有艺术家名称包含引号。

任何帮助将不胜感激,如果您需要任何进一步的解释或数据,请告诉我。

4

2 回答 2

4

使用否定环视删除所有\"既不在逗号之前也不在逗号之后的内容。

(?<!,)\\"(?!,)

演示

> x <- c('user,\"Fall Out Boy\",\"\"The Take Over, The Breaks Over\"\",0,2010,4,17,7,11,37', 'user,\"Gare du Nord\",\"I Want Love 12\" Remix\",0,2011,6,12,19,32,33')
> gsub("(?<!,)\\\"(?!,)", "", x, perl=T)
[1] "user,\"Fall Out Boy\",\"The Take Over, The Breaks Over\",0,2010,4,17,7,11,37"
[2] "user,\"Gare du Nord\",\"I Want Love 12 Remix\",0,2011,6,12,19,32,33" 

请注意,模式参数中需要有一个额外的反斜杠,因为反斜杠是 R 和正则表达式引擎中的转义运算符。

于 2014-10-30T00:01:53.423 回答
2

具有字母数字和双引号以及反向引用的字符类可以做到这一点:

gsub("([ 0-9a-zA-Z\"])(\\\")([ 0-9a-zA-Z\"])", "\\1\\3",test)

[1] "user,\"Fall Out Boy\",\"The Take Over, The Breaks Over\",0,2010,4,17,7,11,37"
[2] "user,\"Gare du Nord\",\"I Want Love 12 Remix\",0,2011,6,12,19,32,33"     

也可以考虑:

gsub("([ [:alpha:][:digit:]\"])(\\\")([ [:alpha:][:digit:]\"\"])", 
     "\\1\\3", test)

基本上删除两侧没有逗号的类的任何双引号。如果您的引号和正确的分隔标记之间有空格,则会崩溃。?regex 页面描述了您使用字符类的选项。括号是反向引用的分隔符:第一个反向引用是'\\1'并且指的是与第一个成对括号内的字符类匹配的字符:([ [:alpha:][:digit:]\"])。通过从替换参数中省略中间反向引用,匹配的双引号被消除。

于 2014-10-29T23:53:36.833 回答