You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Bash脚本调用Tree-sitter删除Lua配置文件中的代码块?

用Tree-sitter在Bash中稳健删除Lua配置块的方案

完全可以通过Tree-sitter操作AST来替代sed,实现更可靠的Lua配置块删除,且能整合到Bash脚本中。以下是具体实现步骤:

1. 安装Tree-sitter及Lua语法支持

首先需要在系统中安装Tree-sitter核心工具,以及Lua语言的语法解析器:

  • 通过包管理器安装Tree-sitter(比如Debian/Ubuntu用sudo apt install tree-sitter,macOS用brew install tree-sitter)
  • 安装Lua语法解析器:tree-sitter install lua

如果要在Python脚本中调用Tree-sitter(更方便操作AST),还需安装Python绑定:

pip install tree-sitter tree-sitter-lua

2. 编写Tree-sitter查询定位目标配置块

假设你的ssh_domains.lua中,目标配置是数组里的table结构,比如:

ssh_domains = {
  {
    name = "dev-server",
    remote_host = "dev.example.com",
    -- 其他配置
  },
  {
    name = "prod-server",
    remote_host = "prod.example.com",
    -- 其他配置
  }
}

要删除指定name对应的table块,需要编写Tree-sitter查询语句,匹配包含目标域名的table节点:

(table
  (field
    name: (identifier) @name
    value: (string) @domain_name
    (#eq? @domain_name "\"TARGET_DOMAIN\"")
  )
) @target_block

这里TARGET_DOMAIN是占位符,后续脚本中会替换为实际要删除的域名。

3. 编写Python脚本处理AST修改

直接用Bash操作AST比较繁琐,我们可以写一个轻量的Python脚本(利用Tree-sitter的Python API)来解析、修改并输出Lua代码,然后在Bash中调用它。示例脚本remove_ssh_domain.py:

import sys
import tree_sitter_lua
from tree_sitter import Language, Parser

def remove_target_domain(target_name, file_path):
    # 构建Lua语言库
    Language.build_library(
        'build/my-languages.so',
        [tree_sitter_lua.__path__[0]]
    )
    lua_lang = Language('build/my-languages.so', 'lua')
    parser = Parser()
    parser.set_language(lua_lang)

    # 读取原文件内容
    with open(file_path, 'r') as f:
        raw_code = f.read()
    tree = parser.parse(raw_code.encode())

    # 替换占位符,执行查询
    query_str = f"""
    (table
      (field
        name: (identifier) @name
        value: (string) @domain_name
        (#eq? @domain_name "\"{target_name}\"")
      )
    ) @target_block
    """
    query = lua_lang.query(query_str)
    captures = query.captures(tree.root_node)

    if not captures:
        print(f"未找到名称为 {target_name} 的配置块", file=sys.stderr)
        return raw_code

    # 获取目标块的字节范围
    target_node = captures[0][0]
    start_idx = target_node.start_byte
    end_idx = target_node.end_byte

    # 处理数组元素删除后的多余逗号问题
    # 向前查找前置逗号
    prev_comma_pos = start_idx - 1
    while prev_comma_pos >= 0 and raw_code[prev_comma_pos] in [' ', '\t', '\n']:
        prev_comma_pos -= 1
    has_prev_comma = prev_comma_pos >= 0 and raw_code[prev_comma_pos] == ','

    # 向后查找后置逗号
    next_comma_pos = end_idx
    while next_comma_pos < len(raw_code) and raw_code[next_comma_pos] in [' ', '\t', '\n']:
        next_comma_pos += 1
    has_next_comma = next_comma_pos < len(raw_code) and raw_code[next_comma_pos] == ','

    # 生成修改后的代码
    if has_prev_comma:
        modified_code = raw_code[:prev_comma_pos] + raw_code[end_idx:]
    elif has_next_comma:
        modified_code = raw_code[:start_idx] + raw_code[next_comma_pos+1:]
    else:
        modified_code = raw_code[:start_idx] + raw_code[end_idx:]

    return modified_code

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("用法: python3 remove_ssh_domain.py <目标域名> <Lua文件路径>", file=sys.stderr)
        sys.exit(1)
    target_domain = sys.argv[1]
    lua_file = sys.argv[2]
    print(remove_target_domain(target_domain, lua_file))

4. 整合到Bash脚本中

编写Bash脚本remove_ssh_config.sh,调用Python脚本完成删除操作,并添加语法校验:

#!/bin/bash

# 检查参数
if [ $# -ne 2 ]; then
    echo "用法: $0 <目标域名> <Lua配置文件路径>"
    exit 1
fi

DOMAIN="$1"
LUA_FILE="$2"
TMP_FILE="${LUA_FILE}.tmp"

# 调用Python脚本生成修改后的内容
python3 remove_ssh_domain.py "$DOMAIN" "$LUA_FILE" > "$TMP_FILE"

# 校验修改后的Lua语法
if tree-sitter parse "$TMP_FILE" > /dev/null 2>&1; then
    # 语法合法,替换原文件
    mv "$TMP_FILE" "$LUA_FILE"
    echo "成功删除域名 ${DOMAIN} 的配置块"
else
    # 语法错误,丢弃临时文件
    rm "$TMP_FILE"
    echo "删除失败:修改后的内容存在语法错误"
    exit 1
fi

注意事项

  • 首次运行Python脚本会生成build/my-languages.so,确保当前目录有写入权限
  • 根据你的实际Lua配置结构,调整Tree-sitter查询语句的匹配规则(比如如果配置块的字段名或结构不同,修改查询逻辑)
  • 操作前建议备份原配置文件,避免意外情况

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 06:22:28