以下glob表达式选择除 index.pug (filddle)以外的所有.pug
文件:
/src/!(index){.pug,.haml,index.haml}
现在假定我们已经成功停止了对haml
的支持,因此必须从上述表达式中删除与haml
相关的所有内容。问题是如何在不对其结构进行根本改变的情况下缩小上述表达?此条件对于创建简单且同时灵活的全局表达式生成算法很重要。
错误的解决方案(.pug
个文件中没有匹配项):
/src/!(index){.pug}
下面的解决方案也是不合适的,因为将来可能会添加新的文件扩展名支持(例如.slim
)。要实现它,我们必须从根本上改变生成以下表达式的算法。
/src/!(index).pug
以下解决方案也不正确,因为我们不能从中排除任意文件。如果我们要排除index.pug
和about.slim
而不是index.slim
和about.pug
,该怎么办?
/src/!(index).+(pug|slim)
换句话说:以上所有解决方案在以下任何一项上均不可扩展:
重要:在此问题中,我们不考虑通过glob
,globby
,gulp.src()
等接收文件考虑单字符串生成。
另外:如果上述问题无法用一个字符串解决,请写上(带解释/注释)。
答案 0 :(得分:2)
您遇到了minimatch支持的特殊语法。 (对于不知道的读者。OP用于说明的站点使用minimatch来评估glob。)您将看到这样的模式:
{a,b,c}
,并了解它与名称a
,b
和c
匹配。括号模式包含一系列用逗号分隔的子模式,如果有任何子模式匹配,则括号模式也会匹配。因此该模式表示“如果文本与a
或b
或c
匹配,则为匹配”。所以你认为
{a,b}
匹配a
和b
。或在散文中,“如果文本与a
或b
相匹配,则为匹配。”更进一步,您认为可以做到这一点:
{a}
的意思是“如果它匹配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
等)