【问题标题】:stringr extraction regex not working as expectedstringr 提取正则表达式未按预期工作
【发布时间】:2021-01-27 05:45:53
【问题描述】:

假设 arg 如下:

\tLUKE\r\n\t\t\t(over comlink)\r\n\t\tGood luck, Lando\r\n\r\n\t\t\t\tLANDO\r\n\t\t\t(into comlink)\r\n\t\tWhen we find Jabba the Hut and \r\n\t\tthat bounty hunter, we'll contact \r\n\t\tyou.\r\n\r\n

我正在尝试使用下面的代码来提取 arg 中以“\t|\n|\r”+几个大写字母开头并以“\r\n\r\n”结尾的所有字符串,但是我没有匹配:

str_extract_all(arg, "(\t|\n|\r)[A-Z]{1}.*?[A-Z]{2}(\r\n\t\t\t).*?(?=(\r\n\r\n))")

我希望此代码的结果是“\tLUKE\r\n\t\t\t(通过 comlink)\r\n\t\t祝你好运,Lando\r\n\r\n " 和 "\tLANDO\r\n\t\t\t(进入 comlink)\r\n\t\t当我们找到小屋贾巴和 \r\n\t\t那个赏金猎人时,我们会联系 \r \n\t\你。\r\n\r\n"。

当我在最后离开积极的前瞻时,匹配会起作用,我会返回 "\tLUKE\r\n\t\t\t" 和 "\tLANDO\r\n\t\ t\t" 符合预期。

str_extract_all(arg, "(\t|\n|\r)[A-Z]{1}.*?[A-Z]{2}(\r\n\t\t\t).*?")

我在这里错过了什么?

【问题讨论】:

    标签: r regex pattern-matching


    【解决方案1】:

    默认情况下,点 (.) 不匹配换行符(例如,请参阅 help(stri_opts_regex) 中的 dotall 选项),这就是为什么 .*? 部分无法捕获您想要的内容。您可以通过(?s) 标志启用此功能:

    str_extract_all(arg, "(?s)(\t|\n|\r)[A-Z]{1,}(\r\n\t\t\t).*?(?=\r\n\r\n)")
    
    [[1]]
    [1] "\tLUKE\r\n\t\t\t(over comlink)\r\n\t\tGood luck, Lando"                                                                      
    [2] "\tLANDO\r\n\t\t\t(into comlink)\r\n\t\tWhen we find Jabba the Hut and \r\n\t\tthat bounty hunter, we'll contact \r\n\t\tyou."
    

    【讨论】:

    • 谢谢!还有一个问题——我有那个多余的 {1} 加上一个点和另一个 [A-Z]{2} 以便捕获可能由两个单词组成的大写名称(如 "\tDARTH VADER\r\n\t \t\t"。我将如何编写正则表达式来捕获这些内容?看起来 {1,} 不太适合。
    • 您可以使用[A-Z ]+ 捕获1个或多个大写字符和空格
    • 我不知道句号与换行符不匹配,而且我多年来一直在为此苦苦挣扎。这个标志很有帮助!
    【解决方案2】:

    如果您以后不需要该值,则可以省略捕获组。还有{1}是多余的,可以去掉。

    使用仅在末尾的模式行 .*? 不会产生任何匹配,因为量词是非贪婪的,并且在它之后没有规则让它放弃任何匹配。

    为了保持模式不那么严格,您可以使用量词而不是指定制表符和换行符的确切数量。


    为防止不必要的回溯,您可以匹配仅包含大写字符的行,然后匹配所有不包含的行。

    ^[^\S\r\n]+[A-Z]+(?:\r?\n(?![^\S\r\n]*[A-Z]+$).*)*
    
    • ^ 字符串开始
    • [^\S\r\n]+ 匹配 1+ 次没有换行符的空白字符
    • [A-Z]+ 匹配 1+ 个大写字符
    • (?:非捕获组
      • \r?\n(?![^\S\r\n]*[A-Z]+$)` 匹配换行符并断言该行不包含单个大写单词
      • .*如果前面的断言为真,则匹配整行
    • )*关闭组并重复0+次以匹配所有行

    Regex demo

    (?m) 用于多行的示例

    library(stringr)
    
    arg <- "\tLUKE\r\n\t\t\t(over comlink)\r\n\t\tGood luck, Lando\r\n\r\n\t\t\t\tLANDO\r\n\t\t\t(into comlink)\r\n\t\tWhen we find Jabba the Hut and \r\n\t\tthat bounty hunter, we'll contact \r\n\t\tyou.\r\n\r\n"
    str_extract_all(arg, "(?m)^[^\\S\\r\\n]+[A-Z]+(?:\\r?\\n(?![^\\S\\r\\n]*[A-Z]+$).*)*")
    

    输出

    [[1]]
    [1] "\tLUKE\r\n\t\t\t(over comlink)\r\n\t\tGood luck, Lando\r\n"                                                                                
    [2] "\t\t\t\tLANDO\r\n\t\t\t(into comlink)\r\n\t\tWhen we find Jabba the Hut and \r\n\t\tthat bounty hunter, we'll contact \r\n\t\tyou.\r\n\r\n"
    

    【讨论】:

      猜你喜欢
      • 2014-04-28
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多