将函数传递给基于 R 正则表达式的工具

Passing function to R regex-based tools

这个字符串操作问题逃过了我的最大努力。我有一个字符串,例如

eg_str="[probability space](posts/probability space.md) is ... [Sigma Field](posts/Sigma Field.md)"

我想用下划线替换 ([wildcard].md) 的通配符中的所有 space。我的第一个想法是使用 gsub 或 stringr 的 str_replace_all 将适当的子字符串传递给一个简单的函数。像

convert_space_to_underscore<-function(string){
    return(str_replace(string," ","_"))
}
normal_eg_str<-gsub("\((.+?)md\)",paste0("(",convert_space_to_underscore("\1"),"md)"),normal_eg_str)

normal_eg_str<-str_replace_all(document,"\((.+?)md\)",paste0("(",convert_space_to_underscore("\1"),".md)"))

当我运行这些然而,似乎传递给convert_space_to_underscore的参数,而不是输出,因为字符串returns不变(如果你出错在 paste0 组件中,假设有 paste0("(",convert_space_to_underscore("\1"),".m)"),然后字符串 returns 为

eg_str="[probability space](posts/probability space.m) is ... [Sigma Field](posts/Sigma Field.m)"

所以我很确定正在发生的事情是 str_replace_all 和 gsub 根本没有评估函数)。

有没有办法强制求值?这将是最理想的,因为它允许正则表达式组件保持一定的可读性。然而,我也欢迎任何纯正则表达式的解决方案——我的尝试都导致了贪婪错误,无论我似乎在哪里洒 ?{0} 特殊字符。 (注意:会有一些匹配的子串超过一个 space 例如 [Dynklin's Pi Lambda](posts/dynklins pi lambda.md)

你可以使用

library(stringr)
eg_str <- "[probability space](posts/probability space.md) is ... [Sigma Field](posts/Sigma Field.md)"
str_replace_all(eg_str, "\([^()]+\.md\)", function(x) gsub(" ", "_", x, fixed=TRUE) )
## => [1] "[probability space](posts/probability_space.md) is ... [Sigma Field](posts/Sigma_Field.md)"

参见 online R demo

注意:要用单个下划线替换一个或多个白色space块,您需要在gsub中使用正则表达式:gsub("\s+", "_", x).

first regex 找到所有

的字符串
  • \( - 从 (
  • 开始
  • [^()]+ - 除了 ()
  • 之外还有一个或多个字符
  • \.md - .md 字符串
  • \) - 并以 )
  • 结尾

然后,匹配被传递给一个匿名函数,该函数将每个正则 space 替换为 _gsub(" ", "_", x, fixed=TRUE))。

基本 R 解决方案(可读性较差,但使用普通正则表达式):

eg_str <- "[probability space](posts/probability space.md) is ... [Sigma Field](posts/Sigma Field.md)"
gsub("(?:\G(?!^)|\()[^()\s]*\K\s+(?=[^()]*\.md\))", "_", eg_str, perl=TRUE)

参见 this R demo online. See this regex demo。详情:

  • (?:\G(?!^)|\() - 前一场比赛结束或 ( 字符
  • [^()\s]* - 除了 () 和 whitespace
  • 之外的任意 0 个或更多字符
  • \K - 匹配重置运算符,丢弃到目前为止匹配的所有文本从整体匹配内存缓冲区
  • \s+ - 一个或多个白色spaces
  • (?=[^()]*\.md\)) - 除了 () 之外应该有零个或多个字符,紧接着是当前位置右侧的 .md)