go file glob


原文链接: go file glob

描述
glob是shell使用的路径匹配符,类似于正则表达式,但是与正则表达式不完全相同。在linux操作中如文件匹配等等其实已经使用了glob通配符。由于其在路径匹配方面的强大,其他语言也有相应的实现。我在使用基于node的gulp时遇到glob匹配文件路径,于是顺便整理一下glob的基础语法和使用。
语法和使用

*     :匹配一个路径部分中0个或多个字符,注意不匹配以.开始的路径,如文件.a。
?     :匹配一个字符。
[…]   :匹配一系列字符,如[abc]匹配字符a, b, c,在[^…]和[!…]表示匹配不在列表中的字符,如[^abc]匹配除了a, b, c以外的字符。
**    :匹配0个或多个子文件夹。
{a,b} :匹配a或则b,a和b也是通配符,可以由其他通配符组成。
!     :排除文件,如!a.js表示排除文件a.js。 

用途和注意点
glob非常强大的用途在于路径匹配,大部分的平台和开发语言都会在配置中使用glob路径匹配,其普遍性几乎使其成为一种标准。但是需注意的是,每个平台和开发语言所支持glob路径匹配可能不完全一样。

Golang Glob

系统自带的filepath.glob(pattern) 是不支持pattern-list {,} 形式的.
github.com/gobwas/glob
编译为给定的模式和字符串(如果模式之后存在)创建Glob作为分隔符。模式语法是:

术语:

`*`     匹配任何非分隔符字符序列 (任意多个字符)
`**`    匹配任何字符序列 (任意多个字符,包含子路径)
`?`    匹配任何单个非分隔符 (任意的一个字符)
`[`[`!`] 字符范围`]`
            字符类(必须是非空的)
`{`pattern-list`}`
            模式选择
c匹配字符c(c!=`*`,`**`,`?`,`\`,`[`,```,`}`)
`\`c匹配字符c

字符范围:

c匹配字符c(c!=`\\`,`-`,`]`)
`\`c匹配字符c
lo`-`hi匹配lo <= c <= hi的字符c

模式列表:

模式{`,`模式}
            逗号分隔(无空格)模式

pattern: { term }
term:

`*`         matches any sequence of non-separator characters
`**`        matches any sequence of characters
`?`         matches any single non-separator character
`[` [ `!` ] { character-range } `]`
            character class (must be non-empty)
`{` pattern-list `}`
            pattern alternatives
c           matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`)
`\` c       matches character c

character-range:

c           matches character c (c != `\\`, `-`, `]`)
`\` c       matches character c
lo `-` hi   matches character c for lo <= c <= hi

pattern-list:

pattern { `,` pattern }
            comma-separated (without spaces) patterns

匹配需要匹配所有名称的模式,而不仅仅是一个子字符串。当模式格式错误时,唯一可能返回的错误是 ErrBadPattern 。

这几天打算仔细看下redis命令,到keys * 时,猜测应该使用的是 glob 模式匹配,就详细找了点资料,总结如下:

  1. 标准glob 模式:
    *
    ?
    [abc]
    [a-z]

  2. 类unix系统,[]还可以使用 '!' - 排除
    [!abc]
    [!a-z]

  3. 在shell中,'!' 表示 'history' 命令的替代。所以,[!abc],可以使用 [^abc] 来替代!!

  4. 类unix下的一些shell(c shell 和 bash)支持额外的解析,称作:'alternation' 或 'brace expansion' - 花括号扩展({})
    1.生成一个集合:

        echo a{p,c,d,b}e        // ape ace ade abe
    但是,不应该在shell脚本中使用,shell将本中,会原样输出:
        echo a{p,c,d,b}e        // a{p,c,d,b}e
    

    2.当 {} 同 通配符结合使用,先解析 {},再正常解析通配符。因此:

    ls *.{jpg,jpeg,png}         // 被解析为:ls *.jpg *.jpeg *.png
    echo *.{png,jp{e,}g} - {}可以嵌套使用     // 被解析为:*.jpg *.jpeg *.png
    

    3.{} 还可以用于按次序排列的区间,2个整型或字符之间,以 '..' 分割

    echo {1..10}
    echo file{1..4}.txt
    // - //
        新版本的bash允许第3个整型,表示步长
        echo {1..10..3}     // 输出:1 4 7 10
    // - //
    

    4.当 {} 结合变量(variable)一起使用,可能必须结合内建的 'eval' 一起使用。

    start = 1; end = 10
    echo {$start..$end}     // 输出 {1..10}
    eval echo {$start..$end}    // 输出 1 2 3 4 5 6 7 8 9 10
    
  5. windows下的cmd.exe
    不支持 [...]

  6. SQL:
    标准sql语句的like操作符,支持 ? 和 *,但不支持 []
    ? == _

    • == %
      glob术语一般不在SQL社区中使用。很多SQL的实现,扩展了like操作符,支持更多的模式匹配


参考文章:

https://en.wikipedia.org/wiki/Glob_(programming)
https://en.wikipedia.org/wiki/Bash_(Unix_shell)#Brace_expansion
https://en.wikipedia.org/wiki/Wildcard_character

redis的glob模式支持:

?
*
[]
[^]

redis的模式匹配,支持的有点少,stackoverflow上有一篇文章,结合 'lua脚本' ,可匹配更多(我们用php应该也可以)

http://stackoverflow.com/questions/29942541/how-to-get-keys-which-does-not-match-a-particular-pattern-in-redis
`