golang基于正则表达式快速查找替换文件内容及名称插件jet的使用

Golang基于正则表达式快速查找替换文件内容及名称插件jet的使用

jet - Just Edit Text

Jet是一个直观且快速的命令行工具,用于使用正则表达式进行查找和替换操作。Jet允许您替换一个或多个文件和目录中由指定正则表达式匹配的所有子字符串。它可以处理作为输入指定的单个文件或整个目录。当给定一个目录时,Jet会递归地查找并替换所有文件和目录名称中的匹配项。

安装

您可以使用Go的包管理器安装Jet:

go install github.com/NicoNex/jet@latest

如果您使用ArchLinux,您可以使用yay、paru或任何替代的AUR助手安装jet:

yay -S jet-edit

如果您没有安装AUR助手:

git clone https://aur.archlinux.org/jet-edit.git
cd jet-edit
makepkg -si

或者您可以克隆此仓库并使用提供的install.sh脚本,该脚本将安装Jet及其手册页以便轻松访问:

./install.sh

使用

Jet允许您替换一个或多个文件和目录中由指定正则表达式匹配的所有子字符串。它支持作为输入指定的单个文件和整个目录。

如果您向Jet提供目录作为输入,它将递归地在目录树中的所有文件中查找和替换文本,并可选地替换文件或目录名称。

您还可以使用-作为文件名从stdin读取并写入stdout。

命令

jet [options] pattern replacement input-files
jet [options] -e pattern1 replacement1 -e pattern2 replacement2 input-files...

选项

  • -p: 将输出打印到stdout而不是写入每个文件。
  • -v: 启用详细模式;解释正在执行的操作。
  • -g string: 仅处理与给定glob模式匹配的文件。
  • -a: 包括隐藏文件(以点开头的文件)。
  • -l int: 目录遍历的最大深度。(默认值:-1表示无限制)
  • -r, --replace-names: 替换文件和目录名称中的匹配项。
  • -n, --names-only: 仅替换名称中的匹配项,忽略文件内容。
  • -e pattern replacement: 指定正则表达式模式和替换。可以多次使用以进行多次替换。
  • -h, --help: 打印帮助消息并退出。

示例

替换my/path1my/path2下文件中所有出现的"foo"为"bar":

jet "foo" "bar" my/path1 my/path2

替换my/path1my/path2下文件中所有出现的"foo"为"bar"和"baz"为"qux":

jet -e "foo" "bar" -e "baz" "qux" my/path1 my/path2

替换my/path1中"foo"为"bar"并将结果打印到stdout,带有详细输出:

jet -p -v "foo" "bar" my/path1

重命名文件和目录,将my/path1下名称中的"foo"替换为"bar",不修改文件内容:

jet -n "foo" "bar" my/path1

替换my/path1下所有文本文件(包括隐藏文件)中的"foo"为"bar"和"baz"为"qux":

jet -g "*.txt" -a -e "foo" "bar" -e "baz" "qux" my/path1

许可证

Jet根据GNU通用公共许可证v3.0授权。


更多关于golang基于正则表达式快速查找替换文件内容及名称插件jet的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于正则表达式快速查找替换文件内容及名称插件jet的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 基于正则表达式的文件内容及名称查找替换

在 Golang 中,我们可以使用正则表达式来高效地处理文件内容和文件名的查找替换操作。下面我将介绍如何使用标准库和第三方库 github.com/bmatcuk/doublestar 来实现这些功能。

1. 文件内容查找替换

使用标准库实现

package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

// ReplaceInFile 在单个文件中进行正则替换
func ReplaceInFile(filePath string, re *regexp.Regexp, replacement string) error {
	// 读取文件内容
	content, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	// 执行正则替换
	newContent := re.ReplaceAllString(string(content), replacement)

	// 写回文件
	return ioutil.WriteFile(filePath, []byte(newContent), 0644)
}

// ReplaceInFiles 在多个文件中进行正则替换
func ReplaceInFiles(rootDir, pattern string, re *regexp.Regexp, replacement string) error {
	return filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 跳过目录
		if info.IsDir() {
			return nil
		}

		// 匹配文件名模式
		matched, err := filepath.Match(pattern, info.Name())
		if err != nil {
			return err
		}

		if matched {
			return ReplaceInFile(path, re, replacement)
		}

		return nil
	})
}

func main() {
	// 示例:将所有.go文件中的"oldText"替换为"newText"
	re := regexp.MustCompile(`oldText`)
	err := ReplaceInFiles(".", "*.go", re, "newText")
	if err != nil {
		fmt.Println("Error:", err)
	}
}

2. 文件名查找替换

使用标准库实现

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
)

// RenameFiles 使用正则表达式重命名文件
func RenameFiles(rootDir string, re *regexp.Regexp, replacement string) error {
	return filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 跳过目录
		if info.IsDir() {
			return nil
		}

		// 获取目录和文件名
		dir := filepath.Dir(path)
		filename := info.Name()

		// 执行正则替换
		newName := re.ReplaceAllString(filename, replacement)

		// 如果文件名有变化,则重命名
		if newName != filename {
			newPath := filepath.Join(dir, newName)
			fmt.Printf("Renaming %s to %s\n", path, newPath)
			return os.Rename(path, newPath)
		}

		return nil
	})
}

func main() {
	// 示例:将所有.txt文件中的"old"替换为"new"
	re := regexp.MustCompile(`old`)
	err := RenameFiles(".", re, "new")
	if err != nil {
		fmt.Println("Error:", err)
	}
}

3. 使用 Jet 插件

Jet 是一个强大的模板引擎,也可以用于文件处理。以下是使用 Jet 结合正则表达式处理文件的示例:

package main

import (
	"fmt"
	"github.com/CloudyKit/jet"
	"regexp"
)

func main() {
	// 创建 Jet 模板集
	set := jet.NewSet(jet.NewOSFileSystemLoader("."))

	// 注册正则替换函数
	set.AddGlobalFunc("regexReplace", func(args jet.Arguments) reflect.Value {
		str := args.Get(0).String()
		pattern := args.Get(1).String()
		replacement := args.Get(2).String()
		
		re := regexp.MustCompile(pattern)
		return reflect.ValueOf(re.ReplaceAllString(str, replacement))
	})

	// 解析模板
	tpl, err := set.GetTemplate("example.jet")
	if err != nil {
		panic(err)
	}

	// 执行模板
	err = tpl.Execute(os.Stdout, nil, map[string]interface{}{
		"content": "This is oldText in the content",
	})
	if err != nil {
		panic(err)
	}
}

对应的 example.jet 文件内容:

{{ regexReplace(content, "oldText", "newText") }}

4. 使用 doublestar 进行更强大的文件匹配

对于更复杂的文件匹配模式,可以使用 doublestar 库:

package main

import (
	"fmt"
	"github.com/bmatcuk/doublestar"
	"os"
	"path/filepath"
	"regexp"
)

func main() {
	// 使用双星号匹配模式
	matches, err := doublestar.Glob("./**/*.{go,txt}")
	if err != nil {
		panic(err)
	}

	re := regexp.MustCompile(`oldPattern`)

	for _, match := range matches {
		// 处理文件内容替换
		content, err := os.ReadFile(match)
		if err != nil {
			fmt.Printf("Error reading %s: %v\n", match, err)
			continue
		}

		newContent := re.ReplaceAllString(string(content), "newPattern")
		err = os.WriteFile(match, []byte(newContent), 0644)
		if err != nil {
			fmt.Printf("Error writing %s: %v\n", match, err)
		}

		// 处理文件名替换
		dir, file := filepath.Split(match)
		newFile := re.ReplaceAllString(file, "newPattern")
		if newFile != file {
			newPath := filepath.Join(dir, newFile)
			err = os.Rename(match, newPath)
			if err != nil {
				fmt.Printf("Error renaming %s to %s: %v\n", match, newPath, err)
			}
		}
	}
}

总结

  1. 对于简单的文件内容替换,可以使用标准库的 regexpfilepath
  2. 对于复杂的文件匹配模式,可以使用 doublestar
  3. Jet 模板引擎适合需要复杂模板处理的场景
  4. 在生产环境中,建议添加更多的错误处理和日志记录

这些方法可以灵活组合使用,根据实际需求选择最适合的方案。

回到顶部