Documentation ¶
Overview ¶
Package bexp implements Brace Expansion mechanism to generate arbitrary strings. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.
Brace expansions may be nested. The results of each expanded string are not sorted; left to right order is preserved. For example,
Parse("a{d,c,b}e") []string{"ade", "ace", "abe"}
Any incorrectly formed brace expansion is left unchanged.
More info about Bash Brace Expansion can be found at https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrEmptyResult representing empty result by parser. ErrEmptyResult = errors.New("result is empty") // ErrUnchangedBraceExpansion for any incorrectly formed brace expansion // where input string is left unchanged. ErrUnchangedBraceExpansion = errors.New("brace expansion left unchanged") )
Functions ¶
func MkdirAll ¶
MkdirAll calls os.MkdirAll on each math from provided string to create a directory tree from brace expansion. Error can be ErrEmptyResult if parsing provided str results no paths or first error of os.MkdirAll.
Example ¶
package main import ( "fmt" "log" "os" "path/filepath" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { const ( rootdir = "/tmp/bexp" treeExp = rootdir + "/{dir1,dir2,dir3/{subdir1,subdir2}}" ) if err := bexp.MkdirAll(treeExp, 0750); err != nil { log.Fatal(err) } defer os.RemoveAll(rootdir) if err := bexp.MkdirAll(rootdir+"/path/unmodified", 0750); err != nil { log.Println(err) return } err := filepath.Walk(rootdir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } fmt.Println(path) return nil }) if err != nil { log.Println(err) return } }
Output: /tmp/bexp /tmp/bexp/dir1 /tmp/bexp/dir2 /tmp/bexp/dir3 /tmp/bexp/dir3/subdir1 /tmp/bexp/dir3/subdir2 /tmp/bexp/path /tmp/bexp/path/unmodified
func Parse ¶
Parse string expresion into BraceExpansion result.
Example ¶
package main import ( "fmt" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { var v []string v = bexp.Parse("/path/unmodified") fmt.Println(v) v = bexp.Parse("file-{a,b,c}.jpg") fmt.Println(v) v = bexp.Parse("-v{,,}") fmt.Println(v) v = bexp.Parse("file{0..2}.jpg") fmt.Println(v) v = bexp.Parse("file{2..0}.jpg") fmt.Println(v) v = bexp.Parse("file{0..4..2}.jpg") fmt.Println(v) v = bexp.Parse("file-{a..e..2}.jpg") fmt.Println(v) v = bexp.Parse("file{00..10..5}.jpg") fmt.Println(v) v = bexp.Parse("{{A..C},{a..c}}") fmt.Println(v) v = bexp.Parse("ppp{,config,oe{,conf}}") fmt.Println(v) v = bexp.Parse("data/{P1/{10..19},P2/{20..29},P3/{30..39}}") fmt.Println(v) }
Output: [/path/unmodified] [file-a.jpg file-b.jpg file-c.jpg] [-v -v -v] [file0.jpg file1.jpg file2.jpg] [file2.jpg file1.jpg file0.jpg] [file0.jpg file2.jpg file4.jpg] [file-a.jpg file-c.jpg file-e.jpg] [file00.jpg file05.jpg file10.jpg] [A B C a b c] [ppp pppconfig pppoe pppoeconf] [data/P1/10 data/P1/11 data/P1/12 data/P1/13 data/P1/14 data/P1/15 data/P1/16 data/P1/17 data/P1/18 data/P1/19 data/P2/20 data/P2/21 data/P2/22 data/P2/23 data/P2/24 data/P2/25 data/P2/26 data/P2/27 data/P2/28 data/P2/29 data/P3/30 data/P3/31 data/P3/32 data/P3/33 data/P3/34 data/P3/35 data/P3/36 data/P3/37 data/P3/38 data/P3/39]
Example (ExpandOsmTiles) ¶
ExampleExpandOsmTiles the example shows how to create Openstreetmap tiles around the desired latitude and longitude coordinates.
https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png https://a.tile.openstreetmap.org/1/1/1.png
package main import ( "fmt" "math" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { x, y, z := getCenterTile(51.03, 13.78, 5) pattern := fmt.Sprintf( "https://tile.openstreetmap.org/%d/{%d..%d}/{%d..%d}.png", z, x-2, x+2, y-2, y+2, ) tiles := bexp.Parse(pattern) fmt.Println("pattern:", pattern) for _, tile := range tiles { fmt.Println(tile) } } func getCenterTile(lat, long float64, zoom int) (z, x, y int) { n := math.Exp2(float64(zoom)) x = int(math.Floor((long + 180.0) / 360.0 * n)) if float64(x) >= n { x = int(n - 1) } y = int(math.Floor((1.0 - math.Log( math.Tan(lat*math.Pi/180.0)+ 1.0/math.Cos(lat*math.Pi/180.0))/ math.Pi) / 2.0 * n)) return x, y, zoom }
Output: pattern: https://tile.openstreetmap.org/5/{15..19}/{8..12}.png https://tile.openstreetmap.org/5/15/8.png https://tile.openstreetmap.org/5/15/9.png https://tile.openstreetmap.org/5/15/10.png https://tile.openstreetmap.org/5/15/11.png https://tile.openstreetmap.org/5/15/12.png https://tile.openstreetmap.org/5/16/8.png https://tile.openstreetmap.org/5/16/9.png https://tile.openstreetmap.org/5/16/10.png https://tile.openstreetmap.org/5/16/11.png https://tile.openstreetmap.org/5/16/12.png https://tile.openstreetmap.org/5/17/8.png https://tile.openstreetmap.org/5/17/9.png https://tile.openstreetmap.org/5/17/10.png https://tile.openstreetmap.org/5/17/11.png https://tile.openstreetmap.org/5/17/12.png https://tile.openstreetmap.org/5/18/8.png https://tile.openstreetmap.org/5/18/9.png https://tile.openstreetmap.org/5/18/10.png https://tile.openstreetmap.org/5/18/11.png https://tile.openstreetmap.org/5/18/12.png https://tile.openstreetmap.org/5/19/8.png https://tile.openstreetmap.org/5/19/9.png https://tile.openstreetmap.org/5/19/10.png https://tile.openstreetmap.org/5/19/11.png https://tile.openstreetmap.org/5/19/12.png
Example (OsExpand) ¶
package main import ( "fmt" "os" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { const treeExp = "$MY_ROOT_DIR/dir{1..3}/{subdir1,subdir2}" mapper := func(varName string) string { if varName == "MY_ROOT_DIR" { return "/my_root" } return "" } str := os.Expand(treeExp, mapper) fmt.Println("str := os.Expand(treeExp, mapper)") fmt.Println(str) fmt.Println("v := bexp.Parse(str)") v := bexp.Parse(str) for _, p := range v { fmt.Println(p) } }
Output: str := os.Expand(treeExp, mapper) /my_root/dir{1..3}/{subdir1,subdir2} v := bexp.Parse(str) /my_root/dir1/subdir1 /my_root/dir1/subdir2 /my_root/dir2/subdir1 /my_root/dir2/subdir2 /my_root/dir3/subdir1 /my_root/dir3/subdir2
Example (OsExpandEnv) ¶
package main import ( "fmt" "os" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { const treeExp = "$MY_ROOT_DIR/dir{1..3}/{subdir1,subdir2}" os.Setenv("MY_ROOT_DIR", "/my_root") str := os.ExpandEnv(treeExp) fmt.Println("str := os.ExpandEnv(treeExp)") fmt.Println(str) fmt.Println("v := bexp.Parse(str)") v := bexp.Parse(str) for _, p := range v { fmt.Println(p) } }
Output: str := os.ExpandEnv(treeExp) /my_root/dir{1..3}/{subdir1,subdir2} v := bexp.Parse(str) /my_root/dir1/subdir1 /my_root/dir1/subdir2 /my_root/dir2/subdir1 /my_root/dir2/subdir2 /my_root/dir3/subdir1 /my_root/dir3/subdir2
func ParseValid ¶
ParseValid is for convienience to get errors on input: 1. ErrEmptyResult when provided string is empty When working with Brace Expansions this method is for convinience to handle only empty string as errors in your program. Note that even then it is actually not invalid. As Brace Expansion docs say: "Any incorrectly formed brace expansion is left unchanged.".
2. ErrUnchangedBraceExpansion when provided string was left unchanged Result will always be `BraceExpansion` with min len 1 to satisfy "Any incorrectly formed brace expansion is left unchanged.".
Example ¶
package main import ( "errors" "fmt" "github.com/happy-sdk/happy/pkg/strings/bexp" ) func main() { empty, err := bexp.ParseValid("") fmt.Printf("%q - %t\n", empty[0], errors.Is(err, bexp.ErrEmptyResult)) abc, err := bexp.ParseValid("abc") fmt.Printf("%q - %t\n", abc[0], errors.Is(err, bexp.ErrUnchangedBraceExpansion)) }
Output: "" - true "abc" - true
Types ¶
type BalancedResult ¶
type BalancedResult struct { Valid bool // is BalancedResult valid Start int // the index of the first match of a End int // the index of the matching b Pre string // the preamble, a and b not included Body string // the match, a and b not included Post string // the postscript, a and b not included }
BalancedResult is returned for the first non-nested matching pair of a and b in str.
func Balanced ¶
func Balanced(a, b, str string) BalancedResult
Balanced returns first non-nested matching pair of a and b in str.
func Range ¶
func Range(a, b, str string) BalancedResult
Range retruns the first non-nested matching pair of a and b in str.
type BraceExpansion ¶
type BraceExpansion []string
BraceExpansion represents bash style brace expansion.
func (BraceExpansion) Result ¶
func (b BraceExpansion) Result() []string
Result is convience to get result as string slice.
func (BraceExpansion) String ¶
func (b BraceExpansion) String() string
String calls strings.Join(b, " ") and returns resulting string.