【问题标题】:Get all unique file names获取所有唯一的文件名
【发布时间】:2019-09-02 17:12:20
【问题描述】:

首先,我是正则表达式的初学者。我有一个看起来像这样的字符串:

     my_folder/foo.xml::someextracontent
     my_folder/foo.xml::someextracontent
     another_folder/foo.xml::someextracontent
     my_folder/bar.xml::someextracontent
     my_folder/bar.xml::someextracontent
     my_folder/hello.xml::someextracontent

我想返回属于my_folder 的唯一XML 文件。所以正则表达式将返回:

my_folder/foo.xml
my_folder/bar.xml
my_folder/hello.xml

我查看了Extract All Unique Lines,这与我需要的很接近,但我不确定从那里去哪里。

我得到的最接近的尝试是(?sm)(my_folder\/.*?.xml)(?=.*\1),它获取了所有重复项,但我想要相反,所以我尝试做一个否定的前瞻而不是(?sm)(my_folder\/.*?.xml)(?!.*\1),但捕获组完全错误。

我的正则表达式中缺少什么?这是正则表达式的链接:https://regex101.com/r/ggY2RB/1

【问题讨论】:

  • 欢迎来到 SO!好问题,尽管使用uniq 或其他实用程序可能会更好地完成这样的任务。您愿意接受非正则表达式解决方案吗?
  • 感谢您的建议!不幸的是,这是在 java 中完成的,所以我不能这样做。我已经更新了标签以反映这一点。我只是想知道是否有只使用正则表达式的解决方案。否则我可以抓取所有文件名并将它们放入一个集合中
  • 如果您使用的是 Java,只需使用 HashSet。我敢打赌它比正则表达式更快。

标签: java regex


【解决方案1】:

您可以使用负前瞻 (?! 来断言右侧的内容不是您在第 1 组中捕获的内容,而不是使用正向前瞻 (?=

在您的模式中,您正在使用 (?s) 使点匹配换行符并使用非贪婪点开始 .*? 但您也可以使用与换行符或正斜杠不匹配的否定字符类。

如果文件夹还可以包含嵌套文件夹,您可以使用重复 0+ 次 1+ 空白字符后跟正斜杠的模式。

(?s)(my_folder/(?:[^/\n]+/)*[^/\n]+\.xml)::(?!.*\1)
  • (?s)
  • (抓拍群
    • my_folder/ 字面上匹配
    • (?:[^/\n]+/)* 重复 0+ 次而不是正斜杠或换行符后跟正斜杠
    • [^/\n]+\.xml 匹配 1+ ot 正斜杠或换行符,后跟 .xml
  • )关闭捕获组
  • ::(?!.*\1) 匹配 :: 然后断言右边的内容不包含第 1 组中捕获的内容

在 Java 中

String regex = "(?s)(my_folder/(?:[^/\\n]+/)*[^/\\n]+\\.xml)::(?!.*\\1)";

Regex demo | Java demo

【讨论】:

  • 谢谢,那(?sm)(my_folder\/.*?.xml)(?!.*\1) 怎么不起作用?捕获组获取所有 XML 文件名,然后如果匹配 .*\1,则负前瞻应该排除匹配项,对吗?我的假设是 my_folder/test.xml::helloworld my_folder/test.xml 应该被排除在外,而是将其全部包含在捕获组中
  • 那是由于不贪心的点星.*?如果匹配不上就会放弃位置直到匹配到。
【解决方案2】:

This RegEx 可能会帮助您找到您可能正在寻找的唯一字符串:

/(\w+\/\w+\.xml)(?![\s\S]*\1)/s

如果你只想匹配my_folder,你可以试试this

 /(\my_folder\/\w+\.xml)(?![\s\S]*\1)/s

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    相关资源
    最近更新 更多