使用R

时间:2018-08-03 14:44:34

标签: r regex stringr

基本上,这是我的输入;

"a ~ b c d*e !r x"
"a ~ b c"
"a ~ b c d1 !r y",
"a ~ b c D !r z",
"a~b c d*e!r z"

并且希望以此作为我的结果;

"b c d*e"
"b c"
"b c d1"
"b c D"
"b c d*e"

输入表示(混合)模型,该模型由三部分组成,即从属部分(~),固定部分和随机部分(!r)。我认为使用捕获组将很容易(example)。困难是随机部分,并不总是存在。

我尝试了不同的操作,如下所示,当然可以分两个步骤进行。但是,我希望有一个(健壮的)正则表达式单行-我认为这应该是可能的。我也利用这些不同的资源来获得灵感。 non-capturing groupsstring replacingstring removal

library(stringr)
txt <- c("a ~ b c d*e !r x",
         "a ~ b c",
         "a ~ b c d1 !r y",
         "a ~ b c D !r z",
         "a~b c d*e!r z")

# Different tries with capture groups
str_replace(txt, "^.*~ (.*) !r.*$", "\\1")
> [1] "b c d*e"       "a ~ b c"       "b c d1"        "b c D"        
> [5] "a~b c d*e!r z"
str_replace(txt, "^(.*~ )(.*)( !r.*)$", "\\2")
> [1] "b c d*e"       "a ~ b c"       "b c d1"        "b c D"        
> [5] "a~b c d*e!r z"
str_replace(txt, "^(.*~)(.*)(!r.*|\n)$", "\\1\\2")
> [1] "a ~ b c d*e " "a ~ b c"      "a ~ b c d1 "  "a ~ b c D "  
> [5] "a~b c d*e"
str_replace(txt, "^(.*) ~ (.*)!r.*($)", "\\2")
> [1] "b c d*e "      "a ~ b c"       "b c d1 "       "b c D "       
> [5] "a~b c d*e!r z"
str_replace(txt, "^.* ~ (.*)(!r.*|\n)$", "\\1")
> [1] "b c d*e "      "a ~ b c"       "b c d1 "       "b c D "       
> [5] "a~b c d*e!r z"


# Multiple steps
step1 <- str_replace(txt, "^.*~\\s*", "")
step2 <- str_replace(step1, "\\s*!r.*$", "")
step2
> "b c d*e" "b c"     "b c d1"  "b c D"   "b c d*e"

编辑:发布后,我一直在玩耍,找到了适合我特定情况的东西。

# My (probably non-robust) solution/monstrosity
str_replace(txt, "(^.*~\\s*(.*)\\s*!r.*$|^.*~\\s*(.*)$)", "\\2\\3")
> "b c d*e " "b c"      "b c d1 "  "b c D "   "b c d*e"

3 个答案:

答案 0 :(得分:3)

使用正向后看前瞻使用str_extract()怎么样?

str_extract(st, "(?<=~)[^!]+") %>% trimws()
[1] "b c d*e" "b c"     "b c d1"  "b c D"   "b c d*e"

我用英语改写:

  

我们正在寻找以〜(?<=~)开头的字符,并且该字符是1个或多个不包含!的字符的序列。 [^!]+,当我们发现符合标准的内容时,我们将停止搜索该字符串(否则使用str_extract_all())。终结处理,如果我们提取的内容在字符串的结尾处有空格,则将其trimws()删除。

数据:

st <- c(
  'a ~ b c d*e !r x',
  'a ~ b c',
  'a ~ b c d1 !r y',
  'a ~ b c D !r z',
  'a~b c d*e!r z'
)

编辑

随着输入示例的增加,很少有更新。不会再次更新。

答案 1 :(得分:3)

我建议从头至尾全部删除,包括第一个波浪号(带有可选的空格),并以第一个!r开头作为整个单词:

gsub("^[^~]+~\\s*|\\s*!r\\b.*", "", txt)

请参见regex demo

详细信息

  • ^-字符串的开头
  • [^~]+-除~以外的1个以上的字符
  • ~-一个~字符
  • \\s*-超过0个空格
  • |-或
  • \\s*-超过0个空格
  • !r-!r子字符串
  • \\b-单词边界
  • .*-字符串的其余部分。

R demo

txt <- c("a ~ b c d*e !r x",
         "a ~ b c",
         "a ~ b c d1 !r y",
         "a ~ b c D !r z",
         "a~b c d*e!r z")
gsub("^[^~]+~\\s*|\\s*!r\\b.*", "", txt)
## => [1] "b c d*e" "b c"     "b c d1"  "b c D"   "b c d*e"

答案 2 :(得分:1)

此模式可让您在第一个捕获组中提取所需的文本:~ ?([\w\*\-\+\/ ]+)(!r)?

第一个捕获组:[\w\*\-\+\/ ]+匹配任何单词字符\w*+-\和空格{{1 }}一次或多次()。将在第二个捕获组(如果有)+之前将其终止。

Demo