一个go写的grep工具,速度还是挺快的

package main
import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sync"
)
type result struct {
	Filename string
	Line string
	LineNumber int
	Error error
}
var strRex string
var filenames []string
var regRex *regexp.Regexp
var wg sync.WaitGroup
var allResults []result
var verbose = false
var recursive string
var recursiveFileList []string
var fileFilter string
var rexfileFilter *regexp.Regexp
var inverseSearch bool
func init() {
	var rexError error
	flag.StringVar(&strRex, "r", "", "Regular expresion to match against the input files")
	flag.BoolVar(&verbose, "v", false, "It sets verbose output (Basically showing filename and line number for each match)")
	flag.BoolVar(&inverseSearch, "i", false, "It does what you might expect.. reverse the search")
	flag.StringVar(&recursive, "R", "", "Recursively find all files starting from the current folder and apply the given search to them")
	flag.StringVar(&fileFilter, "FF", "", "Filter to be applied to the filenames when used recursevily")
	flag.Parse()
	if strRex == "" {
		fmt.Fprintf(os.Stderr, "The '-r' (regular expression flag is mandatory)\n")
		os.Exit(1)
	}
	regRex, rexError = regexp.Compile(strRex)
	if rexError != nil {
		fmt.Fprintf(os.Stderr, "Your regex '%s' cant compile. Error : %s", strRex, rexError.Error())
		os.Exit(2)
	}
	rexfileFilter, rexError = regexp.Compile(fileFilter)
	if rexError != nil {
		fmt.Fprintf(os.Stderr, "Your regex '%s' cant compile. Error : %s", rexfileFilter, rexError.Error())
		os.Exit(3)
	}
	if recursive != "" {
		var err error
		filenames, err = walkDir(recursive)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s", err.Error())
		}
	} else {
		filenames = flag.Args()
	}
}
func main() {
	stat, err := os.Stdin.Stat()
	if err != nil {
		fmt.Fprintf(os.Stderr, "There is an error reading from stdin : %s", err)
		os.Exit(3)
	}
	if (stat.Mode() & os.ModeNamedPipe) != 0 {
		grepStdin(os.Stdin, regRex)
	} else {
		chResults := make(chan *result, 4)
		wg.Add(len(filenames))
		for _, fn := range filenames {
			go grep(fn, regRex, &wg, chResults)
		}
		go func(wait *sync.WaitGroup, ch chan<- *result) {
			wg.Wait()
			close(ch)
		}(&wg, chResults)
		for res := range chResults {
			if verbose {
				formatRes(res, 1)
			} else {
				formatRes(res, 2)
			}
		}
	}
}
func grepStdin(ptr io.Reader, reg *regexp.Regexp) {
	bf := bufio.NewScanner(ptr)
	var lineno = 1
	for bf.Scan() {
		// There is no XOR in Golang, so you ahve to do this :
		if line := bf.Text(); (reg.Match([]byte(line)) && !inverseSearch) || (!reg.Match([]byte(line)) && inverseSearch) {
			formatRes(&result{
				Line: line,
				LineNumber: lineno,
				Error: nil,
			}, 3)
		}
		lineno++
	}
}
func grep(file string, reg *regexp.Regexp, wait *sync.WaitGroup, ch chan<- *result) {
	fd, err := os.Open(file)
	if err != nil {
		ch <- &result{
			Filename: file,
			Error: err,
		}
	}
	bf := bufio.NewScanner(fd)
	var lineno = 1
	for bf.Scan() {
		// There is no XOR in Golang, so you ahve to do this :
		if line := bf.Text(); (reg.Match([]byte(line)) && !inverseSearch) || (!reg.Match([]byte(line)) && inverseSearch) {
			ch <- &result{
				Filename: file,
				Line: line,
				LineNumber: lineno,
				Error: nil,
			}
		}
		lineno++
	}
	wg.Done()
}
func formatRes(r *result, format int) {
	if format == 1 {
		if r.Error == nil {
			fmt.Printf("%d - %s - %s\n", r.LineNumber, r.Filename, r.Line)
		} else {
			fmt.Fprintf(os.Stderr, "%s - %s \n", r.Filename, r.Error)
		}
	}
	if format == 2 {
		if r.Error == nil {
			fmt.Printf("%s\n", r.Line)
		} else {
			fmt.Fprintf(os.Stderr, "%s - %s \n", r.Filename, r.Error)
		}
	}
	if format == 3 {
		if r.Error == nil {
			fmt.Printf("%s\n", r.Line)
		} else {
			fmt.Fprintf(os.Stderr, "%s\n", r.Error)
		}
	}
}
func walkDir(path string) ([]string, error) {
	list := make([]string, 0, 50)
	err := filepath.Walk(".",
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if fileFilter != "" {
				if rexfileFilter.Match([]byte(filepath.Base(path))) {
					list = append(list, path)
				}
			} else {
				list = append(list, path)
			}
			return nil // Unreachable code
		})
	if err != nil {
		return nil, err
	}
	return list, nil
}


用法:
mygrep.exe -r "@CloudFunction\(" -R -v ./
其中如果有(之类的,要用\转义
好的,我可以帮您解答这个问题。 grep是一种常用的文本搜索工具,它可以在文件或文本流中查找指定的字符串,并将包含该字符串的行打印出来。如果您想在C语言中实现类似的功能,可以按照以下步骤进行: 1. 打开文件或者从标准输入读取文本流。 2. 读取每行文本,判断该行是否包含指定的字符串。 3. 如果包含,打印该行。 4. 重复步骤2和3,直到文件或文本流结束。 下面是一个简单的示例代码: ```c #include <stdio.h> #include <string.h> void grep(char *str, FILE *fp) { char line[1024]; while (fgets(line, sizeof(line), fp)) { if (strstr(line, str)) { printf("%s", line); } } } int main(int argc, char *argv[]) { FILE *fp; if (argc < 2) { printf("Usage: %s pattern [file...]\n", argv[0]); return 1; } if (argc == 2) { grep(argv[1], stdin); } else { for (int i = 2; i < argc; i++) { fp = fopen(argv[i], "r"); if (fp == NULL) { fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[i]); continue; } grep(argv[1], fp); fclose(fp); } } return 0; } ``` 在这个示例中,我们定义了一个名为“grep”的函数,它接受两个参数:要搜索的字符串和文件指针。该函数使用fgets逐行读取文件,然后使用strstr检查每个行是否包含指定的字符串。如果找到匹配项,则打印该行。 在主函数中,我们首先检查命令行参数数量是否正确。如果只有一个参数,则从标准输入读取文本流。否则,我们依次打开每个指定的文件,并调用grep函数来搜索指定的字符串。 希望这个例子能够对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值