示例#1
0
func main() {
	myflags := flag.NewFlagSet("tffilter", flag.ExitOnError)
	cfg := &tf.TffilterConfig{}
	cfg.DefineFlags(myflags)

	err := myflags.Parse(os.Args[1:])
	err = cfg.ValidateConfig()
	if err != nil {
		usage(err, myflags)
	}
	if cfg.Help {
		fmt.Fprintf(os.Stderr, "help requested:\n")
		usage(nil, myflags)
	}

	leftover := myflags.Args()

	regs := leftover
	//p("regs = %v", regs)
	if cfg.RegexFile != "" {
		regs, err = tf.ReadNewlineDelimFile(cfg.RegexFile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error reading -regexfile '%s': '%s'\n", cfg.RegexFile, err)
			usage(err, myflags)
		}
		if len(regs) == 0 {
			fmt.Fprintf(os.Stderr, "no regex given from file '%s': specify at least one regex to filter with.\n", cfg.RegexFile)
			showUse(myflags)
			os.Exit(1)
		}
	} else {
		if len(regs) == 0 || (len(regs) == 1 && strings.HasPrefix(regs[0], "-h")) {
			fmt.Fprintf(os.Stderr, "no regex given: specify at least one regex to filter with.\n")
			showUse(myflags)
			os.Exit(1)
		}
	}

	// INVAR: regs specified, and len(regs) > 0

	arrRegex := make([]*regexp.Regexp, 0)
	for i := range regs {
		field := regs[i]
		//fmt.Fprintf(os.Stderr, "compiling regex %d: '%s'\n", i, field)
		re := regexp.MustCompile(field)
		arrRegex = append(arrRegex, re)
	}

	i := int64(1)

	fr := tf.NewFrameReader(os.Stdin, 1024*1024)

	var frame tf.Frame
	var raw []byte
	n := len(regs)
	var allMatched, anyMatched bool

toploop:
	for ; err == nil; i++ {
		_, _, err, raw = fr.NextFrame(&frame)
		if err != nil {
			if err == io.EOF {
				break toploop
			}
			fmt.Fprintf(os.Stderr, "tffilter error from fr.NextFrame() at i=%v: '%v'\n", i, err)
			os.Exit(1)
		}
		str := frame.Stringify(-1, false, false, false)
		// match regex
		matchN := 0
		var o string
		var sub []string
		for _, r := range arrRegex {
			if cfg.Sub {
				sub = r.FindStringSubmatch(str)
				//p("sub back from r.FindStringSubmatch(str='%s')  is '%#v' from regex '%s'", str, sub, regs[j])
				if sub == nil {
					o = ""
				} else {
					o = "hit"
				}
			} else {
				o = r.FindString(str)
			}
			//fmt.Fprintf(os.Stderr, "tffilter at i=%v, matching frame '%s' against regex '%s': output is: '%s'\n", j, str, regs[j], o)
			if o != "" {
				matchN++

				switch {
				// we have a match
				case cfg.Any:
					// found at least one match, we can stop under Any
					switch {
					case cfg.ExcludeMatches:
						continue toploop
					case !cfg.ExcludeMatches:
						goto writeout
					}
				}
			} else {
				// not a match
				switch {
				case !cfg.Any && cfg.ExcludeMatches:
					// we've got to match all n in order to exclude, so we know now that we will include.
					goto writeout

				case !cfg.Any && !cfg.ExcludeMatches:
					// not a match, and all must match to survive the filter, so we can stop
					continue toploop
				}
			}
		}

		allMatched = (matchN == n)
		anyMatched = (matchN > 0)

		switch {
		case cfg.Any && cfg.ExcludeMatches:
			if anyMatched {
				continue toploop
			}
			goto writeout
		case cfg.Any && !cfg.ExcludeMatches:
			if anyMatched {
				goto writeout
			}
			continue toploop
		case !cfg.Any && cfg.ExcludeMatches:
			if allMatched {
				continue toploop
			}
			goto writeout
		case !cfg.Any && !cfg.ExcludeMatches:
			if allMatched {
				goto writeout
			}
			continue toploop
		}
	writeout:
		if cfg.Sub {
			// sub-expression matching and reporting only the sub matches
			//p("sub = %#v", sub)
			sub = sub[1:]
			//p("sub[1:] = %#v", sub)
			nsub := len(sub)
			if nsub > 0 {
				for k := range sub {
					fmt.Printf("%s", sub[k])
					if k < nsub-1 {
						fmt.Printf(" ", sub[k])
					}
				}
				fmt.Printf("\n")
			}
		} else {
			// full record matching
			_, err = os.Stdout.Write(raw)
			if err != nil {
				fmt.Fprintf(os.Stderr, "tffilter stopping at: '%s'", err)
			}
		}
	} // end for toploop

	//fmt.Fprintf(os.Stderr, "field='%s': found %v matches.\n", field, matchCount)
}