Golang中字符串命令替换方法解析(1)
Golang中字符串命令替换方法解析(1)
Unix 系统中的 strings 命令用于打印文件中的可打印字符字符串。
如何用 Go 语言实现一个 strings(1) 命令的替代品?
2 回复
您可以在GNU binutils中找到strings的C语言实现。
更多关于Golang中字符串命令替换方法解析(1)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现类似strings命令的功能,可以通过读取文件并提取可打印字符序列来完成。以下是一个基本实现示例:
package main
import (
"fmt"
"io"
"os"
"unicode"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go-strings <filename>")
os.Exit(1)
}
filename := os.Args[1]
file, err := os.Open(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "Error opening file: %v\n", err)
os.Exit(1)
}
defer file.Close()
printStrings(file)
}
func printStrings(r io.Reader) {
const minLength = 4 // 最小字符串长度,与标准strings命令一致
buf := make([]byte, 4096)
var current []rune
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
fmt.Fprintf(os.Stderr, "Read error: %v\n", err)
break
}
if n == 0 {
break
}
for i := 0; i < n; i++ {
ch := rune(buf[i])
// 检查是否为可打印ASCII字符(包括空格)
if ch >= 32 && ch <= 126 {
current = append(current, ch)
} else {
if len(current) >= minLength {
fmt.Println(string(current))
}
current = nil
}
}
if err == io.EOF {
break
}
}
// 处理文件末尾可能存在的字符串
if len(current) >= minLength {
fmt.Println(string(current))
}
}
更完整的实现可以添加更多strings命令的选项支持:
package main
import (
"flag"
"fmt"
"io"
"os"
"unicode"
)
type config struct {
minLength int
encoding string
radix string
}
func main() {
var cfg config
flag.IntVar(&cfg.minLength, "n", 4, "minimum string length")
flag.StringVar(&cfg.encoding, "e", "ascii", "character encoding")
flag.StringVar(&cfg.radix, "t", "d", "radix for location (d, o, x)")
flag.Parse()
if flag.NArg() < 1 {
fmt.Println("Usage: go-strings [options] <filename>")
flag.PrintDefaults()
os.Exit(1)
}
filename := flag.Arg(0)
file, err := os.Open(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
defer file.Close()
printStringsWithConfig(file, cfg)
}
func printStringsWithConfig(r io.Reader, cfg config) {
buf := make([]byte, 4096)
var current []rune
offset := 0
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
fmt.Fprintf(os.Stderr, "Read error: %v\n", err)
break
}
if n == 0 {
break
}
for i := 0; i < n; i++ {
ch := rune(buf[i])
// 根据编码类型检查字符
var isPrintable bool
switch cfg.encoding {
case "ascii":
isPrintable = ch >= 32 && ch <= 126
case "unicode":
isPrintable = unicode.IsPrint(ch) && ch != '\n' && ch != '\r'
default:
isPrintable = ch >= 32 && ch <= 126
}
if isPrintable {
current = append(current, ch)
} else {
if len(current) >= cfg.minLength {
printStringWithOffset(current, offset-len(current), cfg)
}
current = nil
}
offset++
}
if err == io.EOF {
break
}
}
if len(current) >= cfg.minLength {
printStringWithOffset(current, offset-len(current), cfg)
}
}
func printStringWithOffset(str []rune, offset int, cfg config) {
var offsetStr string
switch cfg.radix {
case "o":
offsetStr = fmt.Sprintf("%o", offset)
case "x":
offsetStr = fmt.Sprintf("%x", offset)
default:
offsetStr = fmt.Sprintf("%d", offset)
}
fmt.Printf("%7s: %s\n", offsetStr, string(str))
}
这个实现支持:
-n选项指定最小字符串长度-e选项指定字符编码(ascii/unicode)-t选项指定偏移量显示格式
编译后使用方式:
go build -o go-strings main.go
./go-strings -n=6 -t=x sample.bin

