R正则表达式(靠近单词)

时间:2012-11-21 19:15:28

标签: regex r

我想知道如何使用正则表达式选择彼此附近的单词。 例如,我想从以下短语中选择数字和单词里程:

"140,000 mostly freeway miles" 
"173k commuter miles. "       
"154K(all highway) miles

我不知道如何填写中间的可选单词:

[0-9]+ ???? miles

* near可以定义为1-3个单词。感谢您指出了这一点。

4 个答案:

答案 0 :(得分:3)

以下是R中的答案。其他答案可以进行一些修改。大多数情况下,他们需要“双重逃脱”,你必须使用配对函数regexprregmatches

x=c("140,000 mostly freeway miles" ,"173k commuter miles. " ,"154K(all highway) miles")


gsub('([[:digit:][:punct:]k]+).*(miles).*', 
     '\\1 \\2', 
     x,
     ignore.case=TRUE)

# [1] "140,000 miles" "173k miles"    "154 miles"    

这表示组编号标点符号或组1中的k。请按照此操作。然后是第2组,即“里程”,其后是其他任何内容。

您还可以使用“普通”正则表达式语法:

gsub('([0-9,k]+).*(miles).*', 
     '\\1 \\2', 
     x,
     ignore.case=TRUE)

但是,我会首先清理数据然后做一些更简单的匹配! (例如tolower并删除标点符号。)

答案 1 :(得分:1)

关于问题域,有许多未解答的问题。除此之外,让我们使用包含问题中提供的样本数据的以下数据进行肯定匹配,并使用一些额外的负数匹配样本数据(我正在使用R version 2.14.1 (2011-12-22)):

x <- c("140,000 mostly freeway miles", "173k commuter miles. ", "154K(all highway) miles", "1,24 almost but not mostly freeway miles", "1,2,3,4K MILES")

1,2,3,4K MILES被添加为否定匹配,因为问题将近似定义为1-3 words apart,并且此字段为“近词”。

如果我们使用以下内容......

sub('[\\d,]+k?\\s+(([^\\s]+\\s+){1,3})miles', '\\1', x, ignore.case = TRUE, perl = TRUE)

......我们得到:

[1] "mostly freeway "
[2] "commuter . "
[3] "154K(all highway) miles"
[4] "1,24 almost but not mostly freeway miles"
[5] "1,2,3,4K MILES"

可能不是你想要的结果。由于数据未规范化,因此必须使用非常复杂的正则表达式模式。正如Justin clean up the data first then do some simpler matching y <- gsub('\\pP+', ' ', x, perl = TRUE) y <- gsub('\\s+', ' ', y, perl = TRUE) y <- gsub('^\\s+|\\s+$', '', y, perl = TRUE) y <- gsub('(\\d)\\s(?=\\d)', '\\1\\2', y, perl = TRUE) 中提到的那样answer

您可以按如下方式对数据进行标准化:

y

请参阅以下参考资料以获取更多信息。这基本上是删除标点并确保单词由单个空格分隔。这将为您留下[1] "140000 mostly freeway miles" [2] "173k commuter miles" [3] "154K all highway miles" [4] "124 almost but not mostly freeway miles" [5] "1234K MILES"

y <- sub('^(?!\\d+k?\\s((?!miles)[^\\s]+\\s){1,3}miles).*$', '', y, ignore.case = TRUE, perl = TRUE)
y
[1] "140000 mostly freeway miles" "173k commuter miles"
[3] "154K all highway miles"      ""
[5] ""

现在删除与您要查找的内容不匹配的行:

y <- sub('^\\d+k?\\s((?!miles)[^\\s]+(\\s(?!miles)[^\\s]+){0,2})\\smiles', '\\1', y, ignore.case = TRUE, perl = TRUE)
y
[1] "mostly freeway" "commuter"       "all highway"    ""
[5] ""

最后,得到“近词”:

{{1}}

可能有更简单的方法来规范化数据,但这会为您提供一些正则表达式示例。

有关详细信息,请参阅:

答案 2 :(得分:0)

使用此正则表达式\d+([.,]\d+)?(?=.*?miles)

答案 3 :(得分:0)

这仍然有点模糊,但是我们假设我们将所有内容定义为由空格分隔的“单词”。因此,如果可能有1-3个单词,那么在数字和miles

之间需要有2-4个空格(实际上我将使第一个可选,看到你的最后一个例子)
\d[\d,.]*k?\s*(\S+\s+){1,3}miles

请注意,您应该使此正则表达式不区分大小写,以匹配kK

另请注意,数字部分当然可以改进。这个将只取第一个数字,然后包括尽可能多的数字,逗号和句号,无论是否有效数字格式。