【问题标题】:Using strsplit() in R, ignoring anything in parentheses在 R 中使用 strsplit(),忽略括号中的任何内容
【发布时间】:2016-02-11 18:45:25
【问题描述】:

我正在尝试在 R 中使用 strsplit() 根据逗号将字符串分成几段,但我不想在括号中拆分任何内容。我认为答案是正则表达式,但我正在努力让代码正确。

例如:

x <- "This is it, isn't it (well, yes)"
> strsplit(x, ", ")
[[1]]
[1] "This is it"     "isn't it (well" "yes)" 

当我想要的是:

[1] "This is it"     "isn't it (well, yes)"

【问题讨论】:

  • 您尝试使用大括号(...) 作为不可拆分的块范围,并且必须将您的意图放入拆分正则表达式中。这不是一项简单的任务。

标签: regex r strsplit


【解决方案1】:

我们可以使用PCRE 正则表达式到FAIL 任何,,其后是() 之前并由, 分割,后跟0 个或多个空格(\\s*

 strsplit(x, '\\([^)]+,(*SKIP)(*FAIL)|,\\s*', perl=TRUE)[[1]]
 #[1] "This is it"           "isn't it (well, yes)"

【讨论】:

    【解决方案2】:

    我建议使用另一个带有(*SKIP)(*F) 的正则表达式来忽略所有(...) 子字符串,并且只匹配带括号的子字符串之外的逗号:

    x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too)"
    strsplit(x, "\\([^()]*\\)(*SKIP)(*F)|\\h*,\\h*", perl=T)
    

    IDEONE demo

    您可以在此处阅读有关How do (*SKIP) or (*F) work on regex? 的更多信息。正则表达式匹配:

    • \( - 一个左括号
    • [^()]* - 除() 之外的零个或多个字符
    • \) - 右括号
    • (*SKIP)(*F) - 将当前正则表达式索引推进到右括号后位置的动词
    • | - 或者...
    • \\h*,\\h* - 用零个或多个水平空格包围的逗号。

    【讨论】:

    • 您是否劫持了 stribizhev 的帐户? o_O
    • @BhargavRao:这是我的账户,我只是改了名字。您可以在 SO 上每月执行一次 :)
    • 这很棒。谢谢!
    【解决方案3】:

    另一种方法:

    添加到@Wiktor 的示例字符串,

    x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too). Let's look, does it work?"
    

    现在是魔法:

    > strsplit(x, ", |(?>\\(.*?\\).*?\\K(, |$))", perl = TRUE)
    [[1]]
    [1] "This is it"                                       
    [2] "isn't it (well, yes)"                             
    [3] "and (well, this, that, and this, too). Let's look"
    [4] "does it work?"  
    

    那么, |(?&gt;\\(.*?\\).*?\\K(, |$)) 是如何匹配的呢?

    • | 捕获任一侧的任一组,两者
      • 在左边,字符串,
      • 在右边,(?&gt;\\(.*?\\).*?\\K(, |$))
        • (?&gt; ... ) 设置 an atomic group,不允许回溯重新评估匹配的内容。
        • 在这种情况下,它会查找左括号 (\\(),
        • 然后任何字符 (.) 从 0 到无限次重复 (*),但尽可能少 (?),即 . 被延迟评估。
        • 先前的. 重复随后被第一个右括号 (\\)) 限制,
        • 后面是另一组重复 0 到尽可能少的任意字符 (.*?)
        • a \\K 结尾,这会丢弃到目前为止的匹配并设置新匹配的起点。
        • 以前的.*? 受捕获组(( ... ))的限制,| 要么
          • 选择一个实际的文本字符串,,
          • 或将\\K 移动到行尾$(如果没有更多逗号)。

    *哇哦。*

    如果我的解释令人困惑,请参阅上面链接的文档,并查看regex101.com,您可以在其中输入上述正则表达式(单转义-\-而不是R 样式的双转义-\\)和一个测试字符串,看看它匹配什么,并得到它在做什么的解释。您需要在正则表达式框旁边的框中设置 g(全局)修饰符以显示所有匹配项,而不仅仅是第一个。

    快乐strspliting!

    【讨论】:

    • 非常有帮助。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 2019-10-04
    • 1970-01-01
    相关资源
    最近更新 更多