如果您确实需要使用 glob,那么您可以列出允许的内容,使其相当于否定:
extglob = "{[^f]*,f,f[^o]*,fo,fo[^o]*,foo?*}/**/*"
File.fnmatch(extglob, "hello/world.js", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true
File.fnmatch(extglob, "test/some/globs", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true
File.fnmatch(extglob, "foo/bar/something.txt", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> false
File.fnmatch(extglob, "food/bar/something.txt", File::FNM_EXTGLOB | File::FNM_PATHNAME)
#=> true
{[^f]*,f,f[^o]*,fo,fo[^o]*,foo?*}
means:
- 任何不以以下字符开头的字符串
f
- 字符串
f
- 任何以以下开头的字符串
f
第二个字符是not a o
- 字符串
fo
- 任何以以下开头的字符串
fo
第三个字符是not a o
- 任何以以下开头的字符串
foo
如果它至少还有一个字符
Update
如果你的字符串文字太长,生成一个否定它的 glob 可能会很痛苦,那么为什么不为它创建一个函数呢?
def extglob_neg str
str.each_char.with_index.with_object([]) do |(_,i),arr|
arr << "#{str[0,i]}[^#{str[i]}]*"
arr << str[0..i]
end.join(',').prepend('{').concat('?*}')
end
extglob_neg "Food"
#=> "{[^F]*,F,F[^o]*,Fo,Fo[^o]*,Foo,Foo[^d]*,Food?*}"
note:我没有在这个函数中实现任何 glob 转义,因为它看起来有点复杂。但我可能是错的