代码之家  ›  专栏  ›  技术社区  ›  tstev

使用R中的stringr包提取输入字符串的特定部分

  •  1
  • tstev  · 技术社区  · 6 年前

    基本上,这是我的输入;

    "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 groups , string replacing string 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 回复  |  直到 6 年前
        1
  •  3
  •   Wiktor Stribiżew    6 年前

    我建议从一开始就全部删除,直到并包括第一个平铺(带有可选的空白)和所有从第一个开始的平铺 !r 整体而言:

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

    regex demo

    细节

    • ^ -字符串开头
    • [^~]+ -除 ~
    • ~ -一个 ~ 烧焦
    • \\s* -0+空格
    • | -或者
    • \\s公司* -0+空格
    • !右 - !右 子串
    • \\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
  •  3
  •   s_baldur    6 年前

    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() ). finalElement,如果我们提取的内容在字符串末尾的开头有空格,则删除它们 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'
    )
    

    编辑

    随着输入示例的增加,已经很少有更新了。将不再更新。

        3
  •  1
  •   Michał Turczyn    6 年前

    此模式允许您使用第一个捕获组提取所需的文本: ~ ?([\w\*\-\+\/ ]+)(!r)? .

    第一个捕获组: [\w\*\-\+\/ ]+ 匹配任何单词字符 \w * , + , - , \ 和空间 一次或多次( + ). 将在第二个捕获组(如果有)之前终止 (!r)? .

    Demo