【问题标题】:Regex matching all characters from the beginning of the string to the first underscore正则表达式匹配从字符串开头到第一个下划线的所有字符
【发布时间】:2016-04-06 10:23:26
【问题描述】:

我正在尝试对向量的元素进行子串化,以仅保留 FIRST 下划线之前的部分。我是一个使用子字符串的新手,还没有完全理解所有的正则表达式。我接近答案,我可以得到我想删除的部分,但仍然看不到如何得到相反的部分。感谢您对正则表达式的任何帮助和/或解释!

我的向量如下所示,在某些元素中有多个下划线

v = c("WL_Alk", "LQ_Frac_C_litter_origin", "MI_Nr_gat", "SED_C_N", "WL_CO2", "WL_S")

我想要的输出看起来像

v_short = c("WL", "LQ", "MI", "SED", "WL", "WL")

获取我想要删除的部分的代码是sub("^[^_]*", "", v)。我想我必须在正则表达式中对 $ 做一些事情,因为sub("[_$]", "", v) 删除了第一个下划线,但我无法让它删除它后面的部分。即使使用正则表达式帮助文件,我还没有完全理解 ^、$ 和 * 的含义,因此也非常感谢您的解释!

【问题讨论】:

  • 好吧,无论如何,我的回答显示了如何真正保留,而不仅仅是删除“字符串”之后的部分。 R removing everything after a string in a data frame column with missing values 只详述了不必要的字符串块删除方法。
  • 对不起,我之前找不到那个(重复的)问题,那个问题也很有帮助!我只发现其他没有解释正则表达式并且与我的问题不完全匹配的人。
  • 这是因为该问题的标题离题了。你知道,一个好的标题意味着更多的OP声誉。还请考虑将您的更改为 Regex 匹配从字符串开头到第一个下划线的所有字符,或类似的东西。其他人会寻找的东西。
  • @WiktorStribiżew:好标题!我一直在与那些斗争

标签: regex r substring


【解决方案1】:

你可以使用

> v = c("WL_Alk", "LQ_Frac_C_litter_origin", "MI_Nr_gat", "SED_C_N", "WL_CO2", "WL_S")
> sub("_.*", "", v)
[1] "WL"  "LQ"  "MI"  "SED" "WL"  "WL" 

"_.*" 模式匹配第一个 _.* 贪婪匹配直到字符串末尾的任何 0+ 个字符(即一次抓取它们)。

使用 stringr str_extract,您可以使用您的模式:

> library(stringr)
> v_short = str_extract(v, "^[^_]*")
> v_short
[1] "WL"  "LQ"  "MI"  "SED" "WL"  "WL" 

^[^_]* 模式匹配字符串的开头和除_ 之外的 0 个或多个字符。

【讨论】:

  • 感谢您的解释!这真的很有帮助,而且效果很好
【解决方案2】:

如果我理解正确

gsub("(.*?)(_.*)","\\1",v,  perl = TRUE)

解释:

(.*?)第一个捕获组;

(_.*)第二个捕获组;

\\1返回第一个捕获组;

【讨论】:

  • 输出是[1] "WL" "LQ_Frac_C_litter" "MI_Nr" "SED_C" "WL" "WL" ,因为(.*)(_.*) 匹配last _
  • non-greedy 改成 (.*?)(_.*) 就可以了
  • @Ciska \\1 是第一个捕获组..您可以这样理解(.*?)..? 使其成为non-greedy 意味着匹配将在第一个下划线出现时立即停止找到
  • 是的,@Ciska,你说得对。我创建了两个“捕获组”(在方括号之间放置一个正则表达式),并且“\\1”只返回第一组;如果你选择“\\2”,你会得到第二组。
  • 正如我所说,这个解决方案对于当前场景来说过于复杂。具有捕获组的正则表达式在性能上不如没有它们的正则表达式。不欢迎混合使用惰性和贪婪的量词,我建议使用 perl=T 然后(众所周知,PCRE 可以很好地处理这些情况)。
【解决方案3】:

有两种方法可以做到这一点。

使用^[^_]+ 并在第一个_ 之前匹配字符串。 Regex101 Demo

使用\_.+$选择第一个_之后的部分并消除它。 Regex101 Demo

【讨论】:

    猜你喜欢
    • 2021-04-15
    • 2018-01-28
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2022-10-01
    • 1970-01-01
    • 2015-02-26
    • 2018-02-13
    相关资源
    最近更新 更多