检查字符串是否为glob模式

时间:2017-02-16 19:30:28

标签: ruby glob

在输入上我有字符串,可以是普通路径字符串(例如/home/user/1.txt)或glob模式(例如/home/user/*.txt)。

接下来我想获得匹配数组,如果string是glob模式,并且在string只是普通路径的情况下我想获得具有单个元素的数组 - 这个路径。

所以我应该检查字符串是否包含未转义的glob符号,如果是,则调用Pathname.glob()来获取匹配,否则只返回带有此字符串的数组。

如何检查字符串是否为glob模式?

更新

我在实施homebrew cask glob pattern support for zap stanza时遇到了这个问题。 我使用的解决方案是进行一些重构,以避免需要检查字符串是否为glob模式。

1 个答案:

答案 0 :(得分:1)

  

接下来我想获得匹配数组,如果string是glob模式,并且在string只是普通路径的情况下我想获得具有单个元素的数组 - 这个路径。

它们都是有效的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字符,但这会很快变得复杂容易出错。它需要knowing how glob works in detail并记住要检查引用和转义。 foo*有一个glob模式。 foo\*没有。 foo[123]foo\[123]没有。而且我不确定foo[123\]正在做什么,我认为它算作一个非终止集。

通常,您希望避免编写必须重现另一段代码的内部工作的代码。如果有Pathname.has_glob_chars你可以使用它,但没有这样的东西。

Pathname.glob使用File.fnmatch进行通配,您可以在不触及文件系统的情况下使用它。你可能能够用它来提出一些东西,但我无法使它发挥作用。我想也许只有文字路径会匹配自己,但foo*会失败。

相反,检查它是否存在。

Pathname.new(path).exist?

如果它存在,它是真实文件的真实路径。如果它不存在,它可能是一条真正的路径,或者它可能是一个全局。这可能已经足够了。

您还可以查看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