package main import ( "flag" "os" "bufio" "strings" "fmt" "log" ) type Opts struct { Compliment bool Delete bool Squeeze bool Truncate bool } type Translator struct { opts Opts TwoArgs bool RuneMap map[rune]rune } func (tr *Translator) ParseOpts() { var from []rune var to []rune tr.RuneMap = make(map[rune]rune) tr.TwoArgs = true flag.BoolVar(&tr.opts.Compliment, "c", false, "Use compliment of array1") flag.BoolVar(&tr.opts.Delete, "d", false, "Delete chars in array1") flag.BoolVar(&tr.opts.Squeeze, "s", false, "Squeeze chars in array2") flag.BoolVar(&tr.opts.Truncate, "t", false, "Truncate array1 to array2 length") flag.Parse() args := flag.Args() if flag.NArg() == 1 { from, to = []rune(args[0]), []rune(args[0]) tr.TwoArgs = false } else if flag.NArg() == 2 { from, to = []rune(args[0]), []rune(args[1]) } else { log.Fatal("USAGE: tr [-c] [-d] [-s] [-t] [array2]") } for i, ch := range from { tr.RuneMap[ch] = to[i] } } func (tr *Translator) Translate(from rune) rune { if !tr.TwoArgs { log.Fatal("translate requires two args") } to, ok := tr.RuneMap[from] if ok { return to } else { return from } } func (tr *Translator) Delete(line string) string { result := make([]rune, 0, len(line)) for _, ch := range []rune(line) { _, ok := tr.RuneMap[ch] if !ok { result = append(result, ch) } } return string(result) } func (tr *Translator) Process(line string) { if tr.opts.Delete { line = tr.Delete(line) } else { line = strings.Map(tr.Translate, line) } fmt.Print(line) } func main() { tr := new(Translator) tr.ParseOpts() scan := bufio.NewScanner(os.Stdin) for scan.Scan() { line := scan.Text() + "\n" tr.Process(line) } }