如果字符串是glob模式,我希望获得匹配数组;如果字符串只是一个普通的路径,则希望获得只有一个元素-该路径的数组。它们都是有效的glob模式。其中一个包含通配符,另一个不包含。将它们都通过
Pathname.glob()
运行,您将始终收到一个数组。奖励是,它会检查是否匹配任何内容。
$ irb
2.3.3 :001 > require "pathname"
=> true
2.3.3 :002 > Pathname.glob("test.data")
=> [#<Pathname:test.data>]
2.3.3 :003 > Pathname.glob("test.*")
=> [#<Pathname:test.asm>, #<Pathname:test.c>, #<Pathname:test.cpp>, #<Pathname:test.csv>, #<Pathname:test.data>, #<Pathname:test.dSYM>, #<Pathname:test.html>, #<Pathname:test.out>, #<Pathname:test.php>, #<Pathname:test.pl>, #<Pathname:test.py>, #<Pathname:test.rb>, #<Pathname:test.s>, #<Pathname:test.sh>]
2.3.3 :004 > Pathname.glob("doesnotexist")
=> []
这是一种很好的方式,可以在程序的早期对数据进行规范化和验证,以便后续程序不必再进行此操作。
如果您真的想确定某个内容是字面路径还是通配符,可以尝试扫描任何特殊的通配符字符,但这很容易变得复杂和容易出错。它需要了解
详细了解glob
的工作原理并记住检查引用和转义。
foo*
是一个通配符模式。
foo\*
不是。
foo[123]
是。
foo\[123]
不是。我不确定
foo[123\]
在做什么,我认为它算作未终止的集合。
一般来说,您希望避免编写必须重现另一个代码片段内部工作方式的代码。如果有一个
Pathname.has_glob_chars
,您可以使用它,但实际上并没有这样的东西。
Pathname.glob
使用 File.fnmatch
进行模式匹配,你可以使用它而不接触文件系统。你可能可以通过使用它来想出一些方法,但我无法使其工作。我以为只有字面路径才能匹配自己,但 foo*
打破了这个假设。
相反,检查它是否存在。
Pathname.new(path).exist?
如果存在,它是指向真实文件的真实路径。如果不存在,它可能是一个真实路径,也可能是一个glob。这应该已经足够了。
您还可以通过查看
Pathname.glob(path)
是否返回与原始路径匹配的单个元素来进行检查。注意,在匹配路径时,使用
cleanpath
对两侧进行规范化非常重要。
paths = Pathname.glob(path)
if paths.size == 1 && paths[0].cleanpath == Pathname.new(path).cleanpath
puts "#{path} is a literal path"
elsif paths.size == 0
puts "#{path} matched nothing"
else
puts "#{path} was a glob"
end
Pathname.glob
就可以做到这一点。判断它是否是字面路径只会增加代码、时间、复杂性和错误。 - undefined