正则表达式:如何在文本中间捕获可选组?

时间:2016-02-24 04:19:42

标签: regex

我正在努力使用正则表达式捕获一些可选文本 - 它位于某些文件名的中间,但不是全部。最大的问题似乎是我的可选组没有锚定(我在它之前和之后使用.*?)。我通过SO的过去答案进行了广泛的研究,但是大部分都能够捕获可选文本,只有它固定在一侧或另一侧(即在行尾)。

鉴于文件名列表,我尝试捕获最多5件事:

  • NAME:始终存在,文件名中的第一件事
  • NUMBER:始终存在,文件名中的第二件事(可能在括号中)
  • SHAPE:永远存在
  • 颜色:有时存在,但可以在形状之前或之后出现
  • 版本:有时会出现,总是会持续到最后(但通常会有垃圾文本)

来源文字:

name 1111 color shape
name 2222 shape color
name 3333 shape
name (4444) color shape version
name.5555.JUNK.color.JUNK.shape.JUNK.version.JUNK

期望的结果:

name (1111) color shape
name (2222) color shape
name (3333) shape
name (4444) color shape version
name (5555) color shape version

但是当我使用这个正则表达式时:

FIND: (.*?).\(?(\d{4}).*?(color)?.*?(shape).*?(color)?.*?(version)?.*
REPLACE: $1 ($2) $3$5 $4 $6

我明白了:

name (1111)  shape
name (2222)  shape
name (3333)  shape
name (4444)  shape
name (5555)  shape

正如您所看到的,通过将(color)(version)捕获群组设为可选,它根本不会捡起它们。 (另外,如果有任何方法可以删除额外的空格,那也很棒。)

顺便说一下,我在每个捕获组之间使用.*?,因为我了解了它的“懒惰”#34;版本.*(不是"贪婪") - 基本上,它尝试尽可能少地匹配而不是尽可能多地匹配。如果您是像我一样的正则表达式新手,请点击此处了解更多信息:http://www.rexegg.com/regex-quantifiers.html#greedytrap

无论如何,我有什么特别明显的遗失吗?或者没有办法通过正则表达式捕获一些可选文本?

PS。这是我的数据预先加载到在线工具上进行播放:http://regexr.com/3cs84 - 我知道正则表达式可以通过语言/平台略有不同,所以如果它有所不同,我最终想要使用这个AppleScript中的正则表达式用于重命名文件和文件夹(可能通过调用终端命令,因为我不认为AppleScript本身支持正则表达式)。

2 个答案:

答案 0 :(得分:0)

尝试将.*?(foo)部分放在(.*?(foo))等括号中,以便?运算符考虑.*?部分。

更正语法(.*?).\(?(\d{4})(.*?(color))?.*?(shape)(.*?(color))?(.*?(version))?.*example

答案 1 :(得分:0)

我对你尝试使用的格式并不是特别熟悉,但我相信我想出的一个例子可以解决你遇到的问题。

http://regexr.com/3cs8g

/name ((\([0-9]+\))|([0-9]+)) ((color shape)|(shape( color)?))( version)?/ig

您所描述的是一个可选子句,可以出现在两个位置之一。所以,你做一个或声明来测试每个可能的位置。