【问题标题】:Match exactly one occurrence and not consecutive occurrences只匹配一次出现而不是连续出现
【发布时间】:2023-03-19 03:05:02
【问题描述】:

我有一个文件名,其中包含从list.files(..., full.names = T) 返回的目录路径。我想将文件名拆分为/ 以查找目录结构。我无法识别单个出现的 /,例如

strsplit("C://dir1/dir2/txt.R", "/")
# [[1]]
# [1] "C:"    ""      "dir1"  "dir2"  "txt.R"

当我希望输出是:

[1] "C://"  "dir1"  "dir2"  "txt.R"

我正在查看this answer,它似乎给出了正则表达式答案,但是,当我尝试获得“文字”匹配时出现错误:

> strsplit("C://dir1/dir2/txt.R", "\/")
Error: '\/' is an unrecognized escape in character string starting ""\/"

事实上,该示例中的正则表达式在 R 中不起作用:

> grepl('([\w\/]+)\/amp(\/\w+[-\/]\w+\/?)', '/name/amp/test-123')
Error: '\w' is an unrecognized escape in character string starting "'([\w"

【问题讨论】:

标签: r regex


【解决方案1】:

试试这个代码:

strsplit("C://dir1/dir2/txt.R", "(?<=//)|(?<!/)/(?!/)", perl=TRUE)

See output here

说明:

  • (?&lt;=//) - 查找紧跟在 // 前面的位置
  • | - 或
  • (?&lt;!/)/(?!/) - 匹配 / 前面既没有 / 也没有后跟 /

Regex Demo

【讨论】:

    【解决方案2】:

    一种选择是匹配不止一次出现的/SKIP,同时在单个// 之后成功的单词边界上进行拆分

    strsplit("C://dir1/dir2/txt.R", "[/]{2,}(*SKIP)(*F)|\\b[/]|(?<=[/])\\b", perl = TRUE)[[1]]
    #[1] "C://"  "dir1"  "dir2"  "txt.R"
    

    【讨论】:

    • 哇。 1)我不知道它会这么复杂。 2) 你是怎么这么快就想出这个正则表达式的?
    • @Alex 谢谢。我按照您描述的逻辑跳过了不止一个 / 的匹配
    • 很好的答案。这样一来,我在本周排名第 9 +1。
    • @TimBiegeleisen 谢谢,是的,很高兴知道您进入前 10 名。继续努力
    【解决方案3】:

    亲吻,

    strsplit("C://dir1/dir2/txt.R", "\\b/\\b|(?<=//)", perl = TRUE)[[1]]
    # [1] "C://"  "dir1"  "dir2"  "txt.R"
    

    【讨论】:

    • Avinash,字边界在这里可能无法正常工作,尤其是在/ 之前或之后有非字字符时。我知道这不是当前的情况,仅供参考。
    • 是的,@WiktorStribiżew 我同意。如果这是一个与 R 相关的问题,那么针对当前上下文的答案就足够了。
    【解决方案4】:

    一个非常简单的匹配方法是

    x <- "C://dir1/dir2/txt.R"
    regmatches(x, gregexpr("[^/]+(?://)?", x))
    #  or with stringr
    str_extract_all(x, "[^/]+(?://)?")
    # [[1]]
    # [1] "C://"  "dir1"  "dir2"  "txt.R"
    

    请参阅regex demoR online demo

    模式详情

    • [^/]+ - 1 个或多个除 / 以外的字符
    • (?://)? - 两个/ 的可选序列。

    注意,如果您想忽略路径中的 // 并且只在开头抓取它们,您可以在可选选项中添加类似 ^[[:alpha:]]:// 或后视 (?&lt;=^[[:alpha:]]:) 的替代选项组:

    regmatches(x, gregexpr("[^/]+(?:(?<=^[[:alpha:]]:)//)?", x, perl=TRUE))
    # or
    regmatches(x, gregexpr("^[[:alpha:]]://|[^/]+", x))
    

    参见thisthat regex demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2018-05-14
      • 2011-02-07
      • 1970-01-01
      相关资源
      最近更新 更多