gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/cmds/core/uniq/uniq.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 // Uniq removes repeated lines. 6 // 7 // Synopsis: 8 // uniq [OPTIONS...] [FILES]... 9 // 10 // Description: 11 // Uniq copies the input file, or the standard input, to the standard 12 // output, comparing adjacent lines. In the normal case, the second and 13 // succeeding copies of repeated lines are removed. Repeated lines must be 14 // adjacent in order to be found. 15 // 16 // Options: 17 // –u: Print unique lines. 18 // –d: Print (one copy of) duplicated lines. 19 // –c: Prefix a repetition count and a tab to each output line. 20 // Implies –u and –d. 21 // –f num: The first num fields together with any blanks before each are 22 // ignored. A field is defined as a string of non–space, non–tab 23 // characters separated by tabs and spaces from its neighbors. 24 // -cn num: The first num characters are ignored. Fields are skipped before 25 // characters. 26 package main 27 28 // TODO(aam): -num and +num are not implemented. they're easy to do, just not exactly the 29 // way that the plan9 uniq does them as we want to avoid polluting the flag parsing libs with 30 // outdated flags. 31 32 import ( 33 "bufio" 34 "bytes" 35 "flag" 36 "fmt" 37 "io" 38 "log" 39 "os" 40 ) 41 42 var uniques = flag.Bool("u", false, "print unique lines") 43 var duplicates = flag.Bool("d", false, "print one copy of duplicated lines") 44 var count = flag.Bool("c", false, "prefix a repetition count and a tab for each output line") 45 46 //var fnum = flag.Int("f", 0, "ignore num fields from beginning of line") 47 //var cnum = flag.Int("cn", 0, "ignore num characters from beginning of line") 48 49 func uniq(f *os.File) { 50 br := bufio.NewReader(f) 51 52 var err error 53 var oline, line []byte 54 cnt := 1 55 isLast := false 56 for { 57 line, err = br.ReadBytes('\n') 58 if err == io.EOF { 59 isLast = true 60 } else if err != nil { 61 log.Printf("Can't read the %v line of %v file: %v", line, f, err) 62 } 63 if oline == nil { 64 oline = line 65 continue 66 } 67 if !bytes.Equal(line, oline) { 68 if *count { 69 fmt.Printf("%d\t%s", cnt, oline) 70 goto skip 71 } 72 if cnt > 1 && *uniques { 73 goto skip 74 } 75 if cnt == 1 && *duplicates { 76 goto skip 77 } 78 fmt.Printf("%s", oline) 79 skip: 80 oline = line 81 cnt = 1 82 } else { 83 cnt++ 84 } 85 if isLast { 86 break 87 } 88 } 89 if cnt > 1 && *uniques { 90 return 91 } 92 if cnt == 1 && *duplicates { 93 return 94 } 95 fmt.Printf("%s", line) 96 } 97 98 func main() { 99 flag.Parse() 100 101 if flag.NArg() > 0 { 102 for _, fn := range flag.Args() { 103 f, err := os.Open(fn) 104 if err != nil { 105 log.Printf("open %s: %v\n", fn, err) 106 os.Exit(1) 107 } 108 uniq(f) 109 f.Close() 110 } 111 } else { 112 uniq(os.Stdin) 113 } 114 }