forked from pachyderm/pachyderm
/
match.go
76 lines (70 loc) · 1.94 KB
/
match.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// match is a regex matching program similar to 'grep'. However, unlike 'grep',
// it's designed to be used in tests. If its input doesn't match its search
// expression, it prints an error to that effect on stderr. If the input *does*
// match, then it's sent to stdout unchanged, so that multiple 'match' commands
// can be chained.
//
// Note that to make the best use of this behavior, 'match' should be used in a
// bash shell after 'set -e -o pipefail', so that a command chaining several
// 'match' commands exits on the first failure and prints its error message
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"os"
"regexp"
)
var invert = flag.Bool("v", false, "If set, match returns an error if the "+
"given regex does not match any text on stdin")
func die(f string, args ...interface{}) {
fmt.Fprintf(os.Stderr, f, args...)
os.Exit(1)
}
func main() {
flag.Parse()
if flag.NArg() == 0 {
die("Must provide a regex to match")
} else if flag.NArg() > 1 {
die("Currently, match can only accept a single regex")
}
re := regexp.MustCompile(flag.Args()[0])
// Read through input looking for match
prefix := &bytes.Buffer{}
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
prefix.Write(s.Bytes())
prefix.Write([]byte{'\n'})
switch {
case !re.Match(s.Bytes()): // No match, continue
case *invert: // Failure -- matched with -v
fmt.Fprintf(
os.Stderr,
"did not expect to find\n \"%s\"\nbut matched\n \"%s\"\nin the text:\n",
flag.Args()[0],
s.Text(),
)
io.Copy(os.Stderr, prefix)
io.Copy(os.Stderr, os.Stdin)
os.Exit(1)
default: // Success, match -- copy input to output
io.Copy(os.Stdout, prefix)
io.Copy(os.Stdout, os.Stdin)
os.Exit(0)
}
}
if !*invert {
// Failure -- no match
fmt.Fprintf(
os.Stderr,
"failed to find\n \"%s\"\nin the text:\n",
flag.Args()[0],
)
io.Copy(os.Stderr, prefix)
os.Exit(1)
}
// Success -- no match with -v
io.Copy(os.Stdout, prefix)
}