github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/freq/freq.go (about) 1 // Copyright 2013-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Freq reads the given files (default standard input) and prints histograms of the 6 // character frequencies. By default, freq counts each byte as a character; under 7 // the –r option it instead counts UTF sequences, that is, runes. 8 // 9 // Synopsis: 10 // 11 // freq [-rdxoc] [FILES]... 12 // 13 // Description: 14 // 15 // Each non–zero entry of the table is printed preceded by the byte value, 16 // in decimal, octal, hex, and Unicode character (if printable). If any 17 // options are given, the –d, –x, –o, –c flags specify a subset of value 18 // formats: decimal, hex, octal, and character, respectively. 19 // 20 // Options: 21 // 22 // –r: treat input as UTF-8 23 // –d: print decimal value 24 // –x: print hex value 25 // –o: print octal value 26 // –c: print character/UTF value 27 package main 28 29 import ( 30 "bufio" 31 "flag" 32 "fmt" 33 "io" 34 "os" 35 "unicode/utf8" 36 ) 37 38 var ( 39 utf = flag.Bool("r", false, "treat input as UTF-8") 40 dec = flag.Bool("d", false, "print decimal value") 41 hex = flag.Bool("x", false, "print hexadecimal value") 42 oct = flag.Bool("o", false, "print octal value") 43 chr = flag.Bool("c", false, "print character/rune") 44 ) 45 46 var freq [utf8.MaxRune + 1]uint64 47 48 func doFreq(f *os.File) { 49 b := bufio.NewReaderSize(f, 8192) 50 51 var r rune 52 var c byte 53 var err error 54 if *utf { 55 for { 56 r, _, err = b.ReadRune() 57 if err != nil { 58 if err != io.EOF { 59 fmt.Fprintf(os.Stderr, "error reading: %v", err) 60 } 61 return 62 } 63 freq[r]++ 64 } 65 } else { 66 for { 67 c, err = b.ReadByte() 68 if err != nil { 69 if err != io.EOF { 70 fmt.Fprintf(os.Stderr, "error reading: %v", err) 71 } 72 return 73 } 74 freq[c]++ 75 } 76 } 77 } 78 79 func main() { 80 flag.Parse() 81 82 if flag.NArg() > 0 { 83 for _, v := range flag.Args() { 84 f, err := os.Open(v) 85 if err != nil { 86 fmt.Fprintf(os.Stderr, "open %s: %v", v, err) 87 os.Exit(1) 88 } 89 doFreq(f) 90 f.Close() 91 } 92 } else { 93 doFreq(os.Stdin) 94 } 95 96 if !(*dec || *hex || *oct || *chr) { 97 *dec, *hex, *oct, *chr = true, true, true, true 98 } 99 100 b := bufio.NewWriterSize(os.Stdout, 8192*4) 101 for i, v := range freq { 102 if v == 0 { 103 continue 104 } 105 106 if *dec { 107 fmt.Fprintf(b, "%3d ", i) 108 } 109 if *oct { 110 fmt.Fprintf(b, "%.3o ", i) 111 } 112 if *hex { 113 fmt.Fprintf(b, "%.2x ", i) 114 } 115 if *chr { 116 if i <= 0x20 || (i >= 0x7f && i < 0xa0) || (i > 0xff && !(*utf)) { 117 b.WriteString("- ") 118 } else { 119 b.WriteRune(rune(i)) 120 b.WriteString(" ") 121 } 122 } 123 fmt.Fprintf(b, "%8d\n", v) 124 } 125 b.Flush() 126 }