» Go创建命令行程序grep » 2. 开发 » 2.8 支持多文件

支持多文件

如果想实现如下的多文件使用方式,需要再次调整 flag 解析逻辑。

gorep pattern file1.txt file2.txt file3.txt

# 或者
gorep pattern *.txt

注意:
在命令行中直接使用 *.txt 作为参数可能不会一定按你的预期工作,因为通配符模式(如 *.txt)的展开是由 shell(例如 Bash)展开的。 Go 中的 flag 模块不会自动执行此展开。不过,你可以使用 filepath.Glob 函数手动展开。

添加多路径版本的 Grep,修改 pkg/grep/search.go:

func GrepMulti(pattern string, filePaths []string, options *Options) (MatchResult, error) {
	if len(filePaths) == 0 {
		return Grep(pattern, "", options)
	}
	result := make(MatchResult)
	for _, filePath := range filePaths {
		grepResult, err := Grep(pattern, filePath, options)
		if err != nil {
			return nil, err
		}
		for k, v := range grepResult {
			result[k] = v
		}
	}
	return result, nil
}


func GrepRecursiveMulti(pattern string, dirPaths []string, options *Options) (MatchResult, error) {
	result := make(MatchResult)
	for _, dirPath := range dirPaths {
		grepResult, err := GrepRecursive(pattern, dirPath, options)
		if err != nil {
			return nil, err
		}
		for k, v := range grepResult {
			result[k] = v
		}
	}
	return result, nil
}

修改 flag 部分,调用多路径版本函数,修改 main.go:

@@ -36,9 +36,9 @@ func main() {
                flag.Usage()
                os.Exit(0)
        }
-       pattern, filePath := args[0], ""
+       pattern, filePaths := args[0], []string{}
        if len(args) > 1 {
-               filePath = args[1]
+               filePaths = args[1:]
        }
 
        options := &grep.Options{}
@@ -52,13 +52,13 @@ func main() {
        var result grep.MatchResult
        var err error
 
-       if *recursiveFlag && filePath != "" {
-               result, err = grep.GrepRecursive(pattern, filePath, options)
+       if *recursiveFlag && len(filePaths) > 0 {
+               result, err = grep.GrepRecursiveMulti(pattern, filePaths, options)
                if err != nil {
                        log.Fatal("Failed to do recursive grep, error:", err)
                }
        } else {
-               result, err = grep.Grep(pattern, filePath, options)
+               result, err = grep.GrepMulti(pattern, filePaths, options)
                if err != nil {
                        log.Fatal("Failed to grep, error:", err)
                }

然后即可执行如下操作:

gorep -n result pkg/grep/*go

# 或者
gorep -n result pkg/grep/search.go pkg/grep/search_test.go

结果:

pkg/grep/search.go:
31: result := make(MatchResult)
38: result[k] = v
41: return result, nil
75: func GrepCount(result MatchResult) int {
77: for _, v := range result {
84: result := make(MatchResult)
91: result[k] = v
94: return result, nil
98: results := make(MatchResult)
105: result, grepErr := Grep(pattern, filePath, options)
109: results[filePath] = result[filePath]
116: return results, nil

pkg/grep/search_test.go:
32: result, err := Grep(pattern, tmpfile.Name(), options)
42: if !reflect.DeepEqual(result, expectedResult) {
43: t.Errorf("Expected %v, but got %v", expectedResult, result)
50: result := make(MatchResult)
51: count := GrepCount(result)
59: result := MatchResult{
68: count := GrepCount(result)
108: result, err := GrepRecursive(pattern, tmpdir, options)
127: if !reflect.DeepEqual(result, expectedResult) {
128: t.Errorf("Expected %v, but got %v", expectedResult, result)

恭喜🎉!你已经用 Go 创建了一个很赞的命令行程序。

项目完整代码:https://github.com/Literank/lr_gorep

持续前进!持续学习!