This is an education project that attempts to reimplement the GNU coreutils in Go. You can find the full manual here:
https://www.gnu.org/software/coreutils/manual/coreutils.html
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
1.8 KiB
100 lines
1.8 KiB
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] <array1> [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)
|
|
}
|
|
}
|
|
|