github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/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  //     freq [-rdxoc] [FILES]...
    11  //
    12  // Description:
    13  //     Each non–zero entry of the table is printed preceded by the byte value,
    14  //     in decimal, octal, hex, and Unicode character (if printable). If any
    15  //     options are given, the –d, –x, –o, –c flags specify a subset of value
    16  //     formats: decimal, hex, octal, and character, respectively.
    17  //
    18  // Options:
    19  //     –r: treat input as UTF-8
    20  //     –d: print decimal value
    21  //     –x: print hex value
    22  //     –o: print octal value
    23  //     –c: print character/UTF value
    24  package main
    25  
    26  import (
    27  	"bufio"
    28  	"flag"
    29  	"fmt"
    30  	"io"
    31  	"os"
    32  	"unicode/utf8"
    33  )
    34  
    35  var utf = flag.Bool("r", false, "treat input as UTF-8")
    36  var dec = flag.Bool("d", false, "print decimal value")
    37  var hex = flag.Bool("x", false, "print hexadecimal value")
    38  var oct = flag.Bool("o", false, "print octal value")
    39  var chr = flag.Bool("c", false, "print character/rune")
    40  
    41  var freq [utf8.MaxRune + 1]uint64
    42  
    43  func doFreq(f *os.File) {
    44  	b := bufio.NewReaderSize(f, 8192)
    45  
    46  	var r rune
    47  	var c byte
    48  	var err error
    49  	if *utf {
    50  		for {
    51  			r, _, err = b.ReadRune()
    52  			if err != nil {
    53  				if err != io.EOF {
    54  					fmt.Fprintf(os.Stderr, "error reading: %v", err)
    55  				}
    56  				return
    57  			}
    58  			freq[r]++
    59  		}
    60  	} else {
    61  		for {
    62  			c, err = b.ReadByte()
    63  			if err != nil {
    64  				if err != io.EOF {
    65  					fmt.Fprintf(os.Stderr, "error reading: %v", err)
    66  				}
    67  				return
    68  			}
    69  			freq[c]++
    70  		}
    71  	}
    72  }
    73  
    74  func main() {
    75  	flag.Parse()
    76  
    77  	if flag.NArg() > 0 {
    78  		for _, v := range flag.Args() {
    79  			f, err := os.Open(v)
    80  			if err != nil {
    81  				fmt.Fprintf(os.Stderr, "open %s: %v", v, err)
    82  				os.Exit(1)
    83  			}
    84  			doFreq(f)
    85  			f.Close()
    86  		}
    87  	} else {
    88  		doFreq(os.Stdin)
    89  	}
    90  
    91  	if !(*dec || *hex || *oct || *chr) {
    92  		*dec, *hex, *oct, *chr = true, true, true, true
    93  	}
    94  
    95  	b := bufio.NewWriterSize(os.Stdout, 8192*4)
    96  	for i, v := range freq {
    97  		if v == 0 {
    98  			continue
    99  		}
   100  
   101  		if *dec {
   102  			fmt.Fprintf(b, "%3d ", i)
   103  		}
   104  		if *oct {
   105  			fmt.Fprintf(b, "%.3o ", i)
   106  		}
   107  		if *hex {
   108  			fmt.Fprintf(b, "%.2x ", i)
   109  		}
   110  		if *chr {
   111  			if i <= 0x20 || (i >= 0x7f && i < 0xa0) || (i > 0xff && !(*utf)) {
   112  				b.WriteString("- ")
   113  			} else {
   114  				b.WriteRune(rune(i))
   115  				b.WriteString(" ")
   116  			}
   117  		}
   118  		fmt.Fprintf(b, "%8d\n", v)
   119  	}
   120  	b.Flush()
   121  }