【问题标题】:Check if string is a glob pattern检查字符串是否是全局模式
【发布时间】:2017-02-16 19:30:28
【问题描述】:

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

接下来,如果字符串是 glob 模式,我想获取匹配数组,如果字符串只是普通路径,我想获取具有单个元素的数组 - 这个路径。

所以我应该以某种方式检查字符串是否包含未转义的 glob 符号,如果确实如此,则调用 Pathname.glob() 以获取匹配项,否则只需返回包含此字符串的数组。

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

更新

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

【问题讨论】:

    标签: ruby glob


    【解决方案1】:

    接下来,如果字符串是 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,您可以尝试扫描任何特殊的 glob 字符,但这很快就会变得复杂并且容易出错。它需要knowing how glob works in detail 并记得检查引用和转义。 foo* 具有全局模式。 foo\* 没有。 foo[123] 确实如此。 foo\[123] 没有。而且我不确定foo[123\] 在做什么,我认为它算作非终止集合。

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

    Pathname.glob 使用 File.fnmatch 来进行 globbing,您可以在不接触文件系统的情况下使用它。你也许可以用它想出一些东西,但我不能让它工作。我想也许只有文字路径会匹配自己,但 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
    

    【讨论】:

    • 是的,普通路径也是有效的 glob 模式(我们称它为微不足道的)。但是全局模式不是有效的路径。我想知道我何时处理非平凡模式以及何时处理普通路径。
    • @mixel 为什么?您想将路径/全局减少为路径列表。 Pathname.glob 就是这样做的。弄清楚它是否是文字路径只会增加代码、时间、复杂性和错误。
    • 我知道,但是需要很长时间才能解释为什么我需要这个,所以我希望有一些标准的方法来检查字符串在 Ruby 中是否是非平凡的 glob 模式。如果除了正则表达式匹配之外没有简单的方法,那么好的,我会尝试弄清楚,或者甚至可能重构我的项目以消除检查的需要。
    • @mixel 你有一个XY problem,可能有更好的方法来解决它。你应该在一个新问题中询问你试图解决的真正问题,即使它很难解释。维护试图确定路径是否包含 glob 的代码将更加困难。
    • 重构似乎是最好的解决方案。您不必检查 glob 是微不足道的还是复杂的,您的代码应该在任何一种情况下都能正常工作。
    猜你喜欢
    • 1970-01-01
    • 2012-09-17
    • 2018-08-21
    • 1970-01-01
    • 2016-02-26
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多