以下glob表达式选择除index.pug(filddle)之外的所有.pug文件:
/src/!(index){.pug,.haml,index.haml}
现在假设我们已经成功停止了对haml的支持,因此必须从上述表达式中删除所有与haml相关的内容.问题是如何在不从根本上改变其结构的情况下减少上述表达?此条件对于创建简单且同时灵活的全局表达式生成算法很重要.
/src/!(index){.pug}
下面的解决方案也不适当,因为将来可能会添加新的文件扩展名支持(例如.slim).要实现它,我们必须从根本上改变生成以下表达式的算法.
/src/!(index).pug
下面的解决方案也是不合适的,因为我们不能从中排除任意文件.如果我们要排除index.pug和about.slim但不排除index.slim和about.pug怎么办?
/src/!(index).+(pug|slim)
换句话说:以上所有解决方案都无法在以下任何方面进行扩展:
>必须选择的文件名
>文件扩展名,必须选择哪些文件
>带有某些扩展名的文件名,必须将其排除在外.
重要说明:在此问题中,我们不考虑通过glob,globby,gulp.src()等接收文件.我们考虑了单个字符串的生成.
并且:如果以上问题无法用一个字符串解决,请写(如带注释/注释).
您已经遇到了minimatch支持的特殊语法. (对于不了解的读者.OP用于说明的站点使用minimatch来评估glob.)您将看到这样的模式:
{a,b,c}
并了解它与名称a,b和c相匹配.括号模式包含一系列用逗号分隔的子模式,如果有任何子模式匹配,则括号模式也会匹配.因此该模式表示“如果文本与OR b OR c匹配,则为匹配”.所以你认为
{a,b}
匹配a和b.或在散文中“如果文本与OR b匹配,则为匹配”.更进一步,您认为可以做到这一点:
{a}
表示“如果匹配,则为匹配”.这相当于仅具有模式a.在没有更好的了解的情况下,有理由认为{a}就是这个意思.在允许对条件列表进行“或”运算的编程语言中,通常可以对仅一个元素的列表执行“或”运算.
但是,minimatch无法以这种方式工作.为了使花括号被识别为表达其他选择,它必须至少包含一个逗号.因此,表达式{a}将使文字输入{a}与花括号和所有内容匹配.
您可以修改生成支撑模式的代码,以便如果子模式列表仅包含一个元素,则可以重复执行.要重用您给出的示例,请在括号中两次输入.pug:
/src/!(index){.pug,.pug}
这样一来,括号将被解释为表示替代方案,而不是按字面意义进行解释.通过重复相同的子模式,匹配文件集不会更改.
另一种解决方案是生成一个支撑模式,该支撑模式始终包含一个无法匹配任何内容的元素.例如:
/src/!(index){.pug,!(*)}
最后一个元素不能匹配任何内容,因此它不会添加匹配项,但是它的存在足以使minimatch根据需要解释括号.
为了提供一些背景信息:minimatch对括号的作用称为“括号扩展”.当给minimatch一个模式a {b,c} d时,在执行其他任何操作之前,它将其转换为两个模式:abc和acd,然后如果任何一个模式都匹配,则认为存在匹配项. Brace扩展是Unix shell与其余的globlob语法一起采用minimatch的方式. (其documentation告诉您看到man sh,man bash等)