NodeJS&Glob:是否必须使用单个字符串排除任何数量的文件名,文件扩展名和文件?

时间:2019-01-20 07:18:20

标签: javascript node.js glob

以下glob表达式选择除 index.pug filddle)以外的所有.pug文件:

/src/!(index){.pug,.haml,index.haml}

现在假定我们已经成功停止了对haml的支持,因此必须从上述表达式中删除与haml相关的所有内容。问题是如何在不对其结构进行根本改变的情况下缩小上述表达?此条件对于创建简单且同时灵活的全局表达式生成算法很重要。

错误的解决方案(.pug个文件中没有匹配项):

/src/!(index){.pug}

下面的解决方案也是不合适的,因为将来可能会添加新的文件扩展名支持(例如.slim)。要实现它,我们必须从根本上改变生成以下表达式的算法。

/src/!(index).pug

以下解决方案也不正确,因为我们不能从中排除任意文件。如果我们要排除index.pugabout.slim而不是index.slimabout.pug,该怎么办?

/src/!(index).+(pug|slim)

换句话说:以上所有解决方案在以下任何一项上均不可扩展:

  • 必须选择的文件名
  • 文件扩展名,必须选择哪些文件
  • 具有某些扩展名的文件名,必须排除。

重要:在此问题中,我们不考虑通过globglobbygulp.src()等接收文件考虑单字符串生成

另外:如果上述问题无法用一个字符串解决,请写上(带解释/注释)。

1 个答案:

答案 0 :(得分:2)

为什么不起作用?

您遇到了minimatch支持的特殊语法。 (对于不知道的读者。OP用于说明的站点使用minimatch来评估glob。)您将看到这样的模式:

{a,b,c}

,并了解它与名称abc匹配。括号模式包含一系列用逗号分隔的子模式,如果有任何子模式匹配,则括号模式也会匹配。因此该模式表示“如果文本与abc匹配,则为匹配”。所以你认为

{a,b}

匹配ab。或在散文中,“如果文本与ab相匹配,则为匹配。”更进一步,您认为可以做到这一点:

{a}

的意思是“如果它匹配a,那么它就是匹配”。这等效于仅具有模式a。在没有更好的了解的情况下,有理由认为{a}就是这个意思。在允许对条件列表进行“或”运算的编程语言中,通常可以对仅一个元素的列表执行“或”运算。

但是,minimatch无法以这种方式工作。 为了使花括号被识别为表示其他选择,它必须至少包含一个逗号。因此,表达式{a}将使文字输入{a}与花括号和一切。

解决方法

您可以修改生成支撑模式的代码,以便如果子模式列表仅包含一个元素,则可以重复执行。要重用您给出的示例,请在括号中使用.pug两次:

/src/!(index){.pug,.pug}

这使得大括号将被解释为表示替代形式,而不是按字面意义进行解释。通过重复相同的子模式,匹配的文件集不会更改。

另一种解决方案是生成一个支撑模式,该支撑模式始终包含一个不能匹配任何内容的元素。例如:

/src/!(index){.pug,!(*)}

最后一个元素不能匹配任何内容,因此它不会添加匹配项,但是它的存在足以使minimatch根据需要解释括号。


为了提供一些背景知识:minimatch对括号的作用称为“括号扩展”。当您为minimatch提供模式a{b,c}d时,然后在执行其他任何操作之前,它会将其转换为两种模式:abcacd,然后认为存在如果任一模式匹配,则为匹配。 Brace扩展是Unix shell与其余的globlob语法一起采用minimatch的方式。 (它的documentation告诉您看到man shman bash等)