├── LICENSE ├── README.md ├── go.mod └── strings.go /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * The names of its contributors may not be used to endorse or 14 | promote products derived from this software without specific prior 15 | written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Strings is a more capable, UTF-8 aware version of the standard strings utility. 2 | For full documentation, see [the godoc page](http://godoc.org/robpike.io/cmd/strings). 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module robpike.io/cmd/strings 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /strings.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go 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 | // Strings is a more capable, UTF-8 aware version of the standard strings utility. 6 | // 7 | // Flags(=default) are: 8 | // 9 | // -ascii(=false) restrict strings to ASCII 10 | // -min(=6) minimum length of UTF-8 strings printed, in runes 11 | // -max(=256) maximum length of UTF-8 strings printed, in runes 12 | // -offset(=false) show file name and offset of start of each string 13 | // 14 | package main // import "robpike.io/cmd/strings" 15 | 16 | import ( 17 | "bufio" 18 | "flag" 19 | "fmt" 20 | "io" 21 | "log" 22 | "os" 23 | "strconv" 24 | ) 25 | 26 | var ( 27 | min = flag.Int("min", 6, "minimum length of UTF-8 strings printed, in runes") 28 | max = flag.Int("max", 256, "maximum length of UTF-8 strings printed, in runes") 29 | ascii = flag.Bool("ascii", false, "restrict strings to ASCII") 30 | offset = flag.Bool("offset", false, "show file name and offset of start of each string") 31 | ) 32 | 33 | var stdout *bufio.Writer 34 | 35 | func main() { 36 | log.SetFlags(0) 37 | log.SetPrefix("strings: ") 38 | stdout = bufio.NewWriter(os.Stdout) 39 | defer stdout.Flush() 40 | 41 | flag.Parse() 42 | if *max < *min { 43 | *max = *min 44 | } 45 | 46 | if flag.NArg() == 0 { 47 | do("", os.Stdin) 48 | } else { 49 | for _, arg := range flag.Args() { 50 | fd, err := os.Open(arg) 51 | if err != nil { 52 | log.Print(err) 53 | continue 54 | } 55 | do(arg, fd) 56 | stdout.Flush() 57 | fd.Close() 58 | } 59 | } 60 | } 61 | 62 | func do(name string, file *os.File) { 63 | in := bufio.NewReader(file) 64 | str := make([]rune, 0, *max) 65 | filePos := int64(0) 66 | print := func() { 67 | if len(str) >= *min { 68 | s := string(str) 69 | if *offset { 70 | fmt.Printf("%s:#%d:\t%s\n", name, filePos-int64(len(s)), s) 71 | } else { 72 | fmt.Println(s) 73 | } 74 | } 75 | str = str[0:0] 76 | } 77 | for { 78 | var ( 79 | r rune 80 | wid int 81 | err error 82 | ) 83 | // One string per loop. 84 | for ; ; filePos += int64(wid) { 85 | r, wid, err = in.ReadRune() 86 | if err != nil { 87 | if err != io.EOF { 88 | log.Print(err) 89 | } 90 | return 91 | } 92 | if !strconv.IsPrint(r) || *ascii && r >= 0xFF { 93 | print() 94 | continue 95 | } 96 | // It's printable. Keep it. 97 | if len(str) >= *max { 98 | print() 99 | } 100 | str = append(str, r) 101 | } 102 | } 103 | } 104 | --------------------------------------------------------------------------------