【问题标题】:regex to match until a colon is found with or without quotes present正则表达式匹配,直到找到带有或不带有引号的冒号
【发布时间】:2021-04-30 08:50:46
【问题描述】:

我正在寻找一个正则表达式来实现以下目标:

当我的输入是root:Folder1:fname 时,我想得到fname

当输入字符串为root:Folder1:'fname' 时再次得到fname (没有引号!)。

对于前者[^:?]*$ 似乎完成了工作,但我找不到一个正则表达式来匹配这两种情况。

是否可以使用单个正则表达式来做到这一点?尝试使用条件正则表达式来实现它,但我做不到。

欢迎任何其他提示/解决方案。

谢谢。

edit:路径的格式不固定,引号可能出现在别处(例如 root:'Folder with spaces1':fname 或 root:'Folder with spaces1':'fname')。我猜的解决方案是向后搜索,因为我们要捕获的文件名在 last 冒号之后是 always。

【问题讨论】:

  • 你的意思是写root:Folder1:'fname'而不是root:Folder1:'name'?
  • @TJ 是的。我编辑了帖子。

标签: regex pcre


【解决方案1】:

当您标记 pcre 时,您还可以使用分支重置组在单引号之间或不在单引号之间获取组 1。

^.*:(?|'(\w+)'|(\w+))$
  • ^ 字符串开始
  • .*: 匹配到最后一个 :
  • (?|分支重置组
    • '(\w+)' 在单引号之间捕获 1+ 个单词字符 | 或 (\w+)捕获1+字字符
  • )关闭分支重置组
  • $字符串结束

Regex demo

【讨论】:

  • 我认为这是唯一好的答案,但删除无用且适得其反的^.*。
【解决方案2】:

如果您的“语法”很严格,这将起作用:

(\w+:)*'?(\w+)'?

  • 首先我们重复任何单词:从 0 到无限次
  • 然后我们使用单引号(如果存在)
  • 然后我们记录最后一个单词
  • 然后我们使用最后一个报价(如果存在)

在此处观看正则表达式调试器: https://regex101.com/r/SjoWYP/1

【讨论】:

  • 亲爱的@DoLooP,格式不严格。我们可以有类似:root:Folder1:'Folder with literal name 1':'fname'。我们确定要捕获最后一个冒号之后的部分,即我们想要的文件名。所以向后搜索可能会更好?我将您的建议更改为 (^:?)*'?(\w+)'?$ (regex101.com/r/I5otrx/1)。它现在得到 fname 和 'fname'。但我们想要的结果是在这两种情况下都得到 fname 作为结果。
  • 你想要一个结果,而不是我得到的子组。然后,您应该使用后视第一组。希望它与您的正则表达式风格兼容。我会尽快修改我的答案。
【解决方案3】:

如果要强制执行成对引号,则需要捕获第一个引号。

(\w+:)*('?)(\w+)\2$

第三对括号内的表达式将作为第三个捕获组($3 或 \3 或 match.group(3) 或你有什么)。

如果您的正则表达式方言允许非分组括号,您可以将其重新表述为

(?:\w+:)*('?)(\w+)\1$

和/或也可能扩展引号组以允许单引号或双引号 (['"]?pro '?)。那么最后一组当然是$2 而不是$3。

【讨论】:

  • 今后,请查看the Stack Overflow regex tag info page 中的指导;您基本上总是需要指定需要解决方案的特定正则表达式工具或方言。这也减少了答案中的对冲词和猜测的数量。
  • 该解决方案在大多数情况下有效,但当文件名包含空格时会失败。我把它改成了 (\w+:)*('?)(\w+[^:?]+)\2$ 现在似乎抓住了每一个案例。
  • 如果您是这个意思,请直接说 [^:] 而不是 \w。严格来说我猜我的\w 应该是[^\W:]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 2016-11-03
  • 1970-01-01
  • 2023-03-27
  • 2010-09-13
  • 1970-01-01
相关资源
最近更新 更多