用于从感兴趣的单词中提取由字符串分隔的数字及其度量单位的正则表达式

Regex to extract a number and its unit of measure that are separated by a string from a word of interest

我正在学习 R 并且正在尝试使用正则表达式来提取特定文本。我想从食谱中获取特定成分的数字和计量单位。

例如以下文本:

text <-  c("0.5 Tb of butter","3 grams (0.75 sticks) of chilled butter","2 tbs softened butter", "0.3 Tb of milk")

我想提取仅与黄油相关的数字和单位,即:

0.5 Tb
3 grams
2 tbs

我认为这最好使用正则表达式来完成,但我对此很陌生,所以我有点吃力。

使用str_match我可以像这样得到特定单位前面的数字:

str_match(text, "\s*(\d+)\s*Tb")
     [,1]   [,2]
[1,] "5 Tb" "5" 
[2,] NA     NA  
[3,] NA     NA  
[4,] "3 Tb" "3" 

但是我怎么能只获得与黄油相关的值和一系列单位。是否可以列出可能的单位(即克、tbs、Tb 等)并要求匹配其中任何一个(以便在本例中克匹配但不匹配)?

或者用一些循环可能会做得更好?我可以将每个句子放入一个数据框中,循环遍历每一行,询问行中是否有 'butter' 在其中搜索一个数字,然后提取数字和后面的单词,这应该是度量单位。

感谢您的帮助。

一个选项是检测字符串中的 'butter' 然后使用 str_extract

str_extract(grep("butter", text, value = TRUE), "[0-9.]+\s+\w+")
#[1] "0.5 Tb"  "3 grams" "2 tbs"

或使用 str_detectstr_extract

library(tidyverse)
str_detect(text, "butter") %>% 
    extract(text, .) %>%
    str_extract("[0-9.]+\s+\w+")
#[1] "0.5 Tb"  "3 grams" "2 tbs"    

你可能想看看这样的东西([\d.]+)\s([a-zA-Z]+).*butter

sub("^(\S+\s+\S+).*", "\1", text[grepl("butter", text)])
[1] "0.5 Tb"  "3 grams" "2 tbs"

\s+ 匹配任意数量的空格,\S+ 匹配任意数量的非空格。 ^ 从头开始​​。

text[grepl("butter", text)] returns 仅包含单词 butter 的文本元素。或许将参数 ignore.case = TRUE 添加到 grepl() 以使其也匹配 Butter...

基本的 R 解决方案是 grep 输出黄油行,然后使用 read.table 解析它们,因为匹配项始终是前两个字段。没有使用包,唯一使用的正则表达式是简单的表达式 butter.

butter <- grep("butter", text, value = TRUE)
read.table(text = butter, fill = TRUE, as.is = TRUE)[1:2]

给予:

   V1    V2
1 0.5    Tb
2 3.0 grams
3 2.0   tbs