脚本如何批量替换项目关键字内容

wen 实用脚本 25

本文目录导读:

脚本如何批量替换项目关键字内容

  1. 使用sed命令(Linux/Mac)
  2. 使用Python脚本
  3. 使用Node.js脚本
  4. 使用自动化工具
  5. 安全建议
  6. 最佳实践

使用sed命令(Linux/Mac)

单个文件替换

# 替换文件中的关键字(直接修改文件)
sed -i 's/旧关键字/新关键字/g' filename.txt
# 替换前备份
sed -i.bak 's/旧关键字/新关键字/g' filename.txt

批量替换目录下所有文件

# 替换当前目录下所有.txt文件
sed -i 's/旧关键字/新关键字/g' *.txt
# 递归替换子目录
find . -name "*.txt" -exec sed -i 's/旧关键字/新关键字/g' {} \;
# 替换多种文件类型
find . \( -name "*.js" -o -name "*.html" -o -name "*.css" \) -exec sed -i 's/旧关键字/新关键字/g' {} \;

使用Python脚本

基础版本

import os
import re
def replace_in_file(file_path, old_text, new_text):
    """在单个文件中替换文本"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        new_content = content.replace(old_text, new_text)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(new_content)
        return True
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {e}")
        return False
def batch_replace(directory, old_text, new_text, file_extensions):
    """批量替换目录中的文件"""
    for root, dirs, files in os.walk(directory):
        for file in files:
            if any(file.endswith(ext) for ext in file_extensions):
                file_path = os.path.join(root, file)
                if replace_in_file(file_path, old_text, new_text):
                    print(f"已替换: {file_path}")
# 使用示例
batch_replace('./project', '旧关键字', '新关键字', ['.js', '.html', '.css'])

高级版本(支持正则表达式)

import os
import re
import json
from pathlib import Path
class BatchReplacer:
    def __init__(self, config_file=None):
        self.replacement_rules = []
        if config_file and os.path.exists(config_file):
            self.load_config(config_file)
    def add_rule(self, pattern, replacement, use_regex=False):
        """添加替换规则"""
        self.replacement_rules.append({
            'pattern': pattern,
            'replacement': replacement,
            'use_regex': use_regex
        })
    def load_config(self, config_file):
        """从配置文件加载替换规则"""
        with open(config_file, 'r', encoding='utf-8') as f:
            configs = json.load(f)
            for config in configs:
                self.add_rule(
                    config['pattern'],
                    config['replacement'],
                    config.get('use_regex', False)
                )
    def replace_text(self, text):
        """应用所有替换规则"""
        result = text
        for rule in self.replacement_rules:
            if rule['use_regex']:
                result = re.sub(rule['pattern'], rule['replacement'], result)
            else:
                result = result.replace(rule['pattern'], rule['replacement'])
        return result
    def replace_in_file(self, file_path):
        """在文件中替换"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            new_content = self.replace_text(content)
            if new_content != content:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(new_content)
                return True
            return False
        except Exception as e:
            print(f"处理文件 {file_path} 时出错: {e}")
            return False
    def batch_replace(self, directory, file_patterns=['*.*'], 
                     exclude_dirs=['node_modules', '.git', '__pycache__']):
        """批量替换"""
        directory = Path(directory)
        replaced_count = 0
        for pattern in file_patterns:
            for file_path in directory.rglob(pattern):
                # 排除指定目录
                if any(excluded in str(file_path) for excluded in exclude_dirs):
                    continue
                if file_path.is_file():
                    if self.replace_in_file(str(file_path)):
                        replaced_count += 1
                        print(f"已替换: {file_path}")
        print(f"\n总共替换了 {replaced_count} 个文件")
# 使用示例
replacer = BatchReplacer()
# 添加替换规则
replacer.add_rule('api.example.com', 'api.newdomain.com')
replacer.add_rule(r'\bpassword\b', 'secret', use_regex=True)
# 或从配置文件加载
# replacer.load_config('replace_rules.json')
# 执行批量替换
replacer.batch_replace(
    './myproject',
    file_patterns=['*.js', '*.html', '*.json', '*.py'],
    exclude_dirs=['node_modules', '.git']
)

配置文件示例 (replace_rules.json)

[
    {
        "pattern": "old_api_key_123",
        "replacement": "new_api_key_456",
        "use_regex": false
    },
    {
        "pattern": "\\bhttp://\\b",
        "replacement": "https://",
        "use_regex": true
    },
    {
        "pattern": "v1.0",
        "replacement": "v2.0",
        "use_regex": false
    }
]

使用Node.js脚本

const fs = require('fs');
const path = require('path');
class BatchReplacer {
    constructor(options = {}) {
        this.extensions = options.extensions || ['.js', '.html', '.css', '.json'];
        this.excludeDirs = options.excludeDirs || ['node_modules', '.git'];
    }
    async replaceInFile(filePath, oldText, newText) {
        try {
            let content = await fs.promises.readFile(filePath, 'utf8');
            if (content.includes(oldText)) {
                content = content.split(oldText).join(newText);
                await fs.promises.writeFile(filePath, content, 'utf8');
                return true;
            }
            return false;
        } catch (error) {
            console.error(`处理文件 ${filePath} 时出错:`, error);
            return false;
        }
    }
    async batchReplace(directory, replacements) {
        const directoryPath = path.resolve(directory);
        let replacedCount = 0;
        const processDirectory = async (dirPath) => {
            const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
            for (const entry of entries) {
                const fullPath = path.join(dirPath, entry.name);
                if (entry.isDirectory()) {
                    if (!this.excludeDirs.includes(entry.name)) {
                        await processDirectory(fullPath);
                    }
                } else if (entry.isFile()) {
                    const ext = path.extname(entry.name);
                    if (this.extensions.includes(ext)) {
                        for (const { oldText, newText } of replacements) {
                            if (await this.replaceInFile(fullPath, oldText, newText)) {
                                replacedCount++;
                                console.log(`已替换: ${fullPath}`);
                            }
                        }
                    }
                }
            }
        };
        await processDirectory(directoryPath);
        console.log(`\n总共替换了 ${replacedCount} 个文件`);
    }
}
// 使用示例
const replacer = new BatchReplacer({
    extensions: ['.js', '.ts', '.html', '.css', '.json'],
    excludeDirs: ['node_modules', '.git', 'dist']
});
replacer.batchReplace('./myproject', [
    { oldText: 'old.api.com', newText: 'new.api.com' },
    { oldText: 'version: "1.0"', newText: 'version: "2.0"' }
]);

使用自动化工具

VSCode全局替换

  1. Ctrl+Shift+F(Mac: Cmd+Shift+F
  2. 输入要搜索的关键字
  3. 点击替换按钮,输入新内容
  4. 可以选择按文件类型过滤

使用grep和sed组合

# 查找包含特定内容的文件
grep -rl "旧关键字" . --include="*.js" --exclude-dir=node_modules
# 结合xargs进行批量替换
grep -rl "旧关键字" . --include="*.js" | xargs sed -i 's/旧关键字/新关键字/g'

安全建议

替换前备份

# 创建备份目录
mkdir -p backup
# 复制原文件到备份
cp -r project backup/
# 或者使用版本控制
git add .
git commit -m "备份,准备进行关键字替换"

预览更改

# 预览替换(不实际修改文件)
def preview_replacements(directory, old_text, new_text, file_extensions):
    for root, dirs, files in os.walk(directory):
        for file in files:
            if any(file.endswith(ext) for ext in file_extensions):
                file_path = os.path.join(root, file)
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                if old_text in content:
                    count = content.count(old_text)
                    print(f"文件: {file_path} - 发现 {count} 处匹配")

最佳实践

  1. 先备份:始终在替换前备份项目
  2. 小范围测试:先在单个文件或小目录测试
  3. 使用版本控制:用git等工具跟踪变更
  4. 区分大小写:注意是否需要大小写敏感
  5. 验证结果:替换后运行测试确保功能正常

选择哪种方法取决于你的具体需求、操作系统和技术栈,如果是一次性的简单替换,推荐使用sed或VSCode的全局替换功能;如果是复杂的、需要灵活配置的替换任务,建议使用Python脚本。

抱歉,评论功能暂时关闭!