Terminal函数自动加载器

发布于:2025-04-14 ⋅ 阅读:(101) ⋅ 点赞:(0)

函数自动加载器

获取~/.config/shell_functions目录下的所有shell文件中的函数,将函数注册到~/.bashrc文件,方便终端使用

一、创建shell函数目录

mkdir -p ~/.config/shell_functions

二、添加功能函数

1. 添加函数加载器

cat > ~/.config/shell_functions/function_loader.sh <<'EOF'
#!/bin/bash

# ====================== 函数自动加载器 ======================
# 文件位置: ~/.config/shell_functions/function_loader.sh

# 颜色定义
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'
COLOR_YELLOW='\033[0;33m'
COLOR_BLUE='\033[0;34m'
COLOR_CYAN='\033[0;36m'
COLOR_RESET='\033[0m'

# 主加载函数
__load_shell_function() {
    local func_name="$1"
    local loaded_files=()

    for func_file in ~/.config/shell_functions/*.sh; do
        [[ "$func_file" == *"function_loader.sh" ]] && continue

        if [[ -f "$func_file" ]]; then
            if grep -q -E "^(function[[:space:]]+)?${func_name}[[:space:]]*[({]" "$func_file"; then
                if [[ ! " ${loaded_files[*]} " =~ " ${func_file} " ]]; then
                    source "$func_file"
                    loaded_files+=("$func_file")
                fi
                return 0
            fi
        fi
    done

    echo -e "${COLOR_RED}错误: 未找到函数 ${func_name} 的实现${COLOR_RESET}" >&2
    return 1
}

# 安全提取函数名
__extract_function_name() {
    local line="$1"
    # 严格匹配函数定义行
    if [[ "$line" =~ ^[[:space:]]*(function[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*[\(\{] ]]; then
        echo "${BASH_REMATCH[2]}"
    fi
}

# 动态发现所有可用函数
__discover_shell_functions() {
    declare -A FUNC_CATEGORIES
    declare -a SHELL_FUNCTIONS=()

    for func_file in ~/.config/shell_functions/*.sh; do
        [[ "$func_file" == *"function_loader.sh" ]] && continue

        if [[ -f "$func_file" ]]; then
            local category=$(basename "$func_file" .sh)
            local functions_in_file=()

            # 逐行读取文件内容
            while IFS= read -r line; do
                # 跳过注释行和空行
                [[ "$line" =~ ^[[:space:]]*# ]] && continue
                [[ -z "${line//[[:space:]]/}" ]] && continue

                # 提取函数名
                local func_name=$(__extract_function_name "$line")
                [[ -n "$func_name" ]] && functions_in_file+=("$func_name")
            done < "$func_file"

            # 过滤私有函数并去重
            local public_functions=()
            for func in $(printf "%s\n" "${functions_in_file[@]}" | sort -u); do
                [[ "$func" != _* ]] && public_functions+=("$func")
            done

            # 添加到分类
            if (( ${#public_functions[@]} > 0 )); then
                FUNC_CATEGORIES["$category"]="${public_functions[*]}"
                SHELL_FUNCTIONS+=("${public_functions[@]}")
            fi
        fi
    done

    # 显示分类信息(不包含在函数列表中)
    echo -e "${COLOR_BLUE}\n可用命令分类:${COLOR_RESET}" >&2
    for category in $(printf "%s\n" "${!FUNC_CATEGORIES[@]}" | sort); do
        echo -e "${COLOR_YELLOW}${category}:${COLOR_RESET}" >&2
        echo "${FUNC_CATEGORIES[$category]}" | tr ' ' '\n' | sed 's/^/  /' >&2
    done

    # 返回去重后的函数列表
    printf "%s\n" "${SHELL_FUNCTIONS[@]}" | sort -u
}

# 安全创建函数桩
__create_function_stub() {
    local func="$1"

    # 验证函数名是否有效
    if [[ "$func" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] && [[ -n "$func" ]]; then
        if ! declare -f "$func" >/dev/null 2>&1; then
            eval "function ${func}() { __load_shell_function \"${func}\" && \"${func}\" \"\$@\"; }"
        fi
    else
        echo -e "${COLOR_RED}警告: 跳过无效函数名 '${func}'${COLOR_RESET}" >&2
    fi
}

# 主初始化过程
function __init_function_loader() {
    # 初始化数组
    local all_functions=()

    # 发现所有函数
    mapfile -t all_functions < <(__discover_shell_functions)

    # 为每个函数创建桩
    for func in "${all_functions[@]}"; do
        __create_function_stub "$func"
    done

    # 显示统计信息
    echo -e "\n${COLOR_GREEN}已注册 ${#all_functions[@]} 个延迟加载函数${COLOR_RESET}" >&2
    echo -e "${COLOR_CYAN}提示: 首次使用命令时会自动加载相应模块${COLOR_RESET}" >&2
}

# 执行初始化
__init_function_loader
EOF

2. 添加功能函数

以添加 proxy_utils.sh 为例(该函数功能在于能够便捷地开关代理,其中的代理端口、测试地址等根据实际情况改写)

cat > ~/.config/shell_functions/proxy_utils.sh <<'EOF'
#!/bin/bash

# ====================== 代理控制模块 ======================
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 配置区(修改这里适应你的环境)
PROXY_HOST="127.0.0.1"
HTTP_PORT="7897"
SOCKS_PORT="7897"
NO_PROXY="localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,.internal,.local"
TEST_URL="https://www.google.com"  # 用于测试代理的网站
DIRECT_TEST_URL="https://www.baidu.com"  # 用于测试直连的网站
TIMEOUT=3  # 测试超时时间(秒)

# 网络测试函数
_test_connection() {
    local url=$1
    local proxy_type=$2
    local proxy_addr=$3

    echo -e "${CYAN}测试连接: $url ...${NC}"

    local start_time=$(date +%s.%N)

    if [ -z "$proxy_type" ]; then
        # 直连测试
        if curl -Is "$url" --connect-timeout $TIMEOUT &>/dev/null; then
            local end_time=$(date +%s.%N)
            local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
            echo -e "${GREEN}✓ 直连成功 (${elapsed}s)${NC}"
            return 0
        else
            echo -e "${RED}✗ 直连失败${NC}"
            return 1
        fi
    else
        # 代理测试
        case $proxy_type in
            http)
                if curl -Is "$url" --connect-timeout $TIMEOUT -x "$proxy_addr" &>/dev/null; then
                    local end_time=$(date +%s.%N)
                    local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
                    echo -e "${GREEN}✓ HTTP代理成功 (${elapsed}s)${NC}"
                    return 0
                else
                    echo -e "${RED}✗ HTTP代理失败${NC}"
                    return 1
                fi
                ;;
            socks5)
                if curl -Is "$url" --connect-timeout $TIMEOUT --socks5-hostname "$proxy_addr" &>/dev/null; then
                    local end_time=$(date +%s.%N)
                    local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
                    echo -e "${GREEN}✓ SOCKS5代理成功 (${elapsed}s)${NC}"
                    return 0
                else
                    echo -e "${RED}✗ SOCKS5代理失败${NC}"
                    return 1
                fi
                ;;
        esac
    fi
}

# 状态检测
_proxy_status_check() {
    echo -e "${BLUE}====== 代理状态 ======${NC}"
    [ -n "$http_proxy" ] && echo -e "HTTP 代理: ${GREEN}已启用${NC} ($http_proxy)" || echo -e "HTTP 代理: ${RED}未启用${NC}"
    [ -n "$https_proxy" ] && echo -e "HTTPS 代理: ${GREEN}已启用${NC} ($https_proxy)" || echo -e "HTTPS 代理: ${RED}未启用${NC}"
    [ -n "$all_proxy" ] && echo -e "SOCKS 代理: ${GREEN}已启用${NC} ($all_proxy)" || echo -e "SOCKS 代理: ${RED}未启用${NC}"
    echo -e "${BLUE}=====================${NC}"
}

# 启用代理
proxy_on() {
    export http_proxy="http://${PROXY_HOST}:${HTTP_PORT}"
    export https_proxy="http://${PROXY_HOST}:${HTTP_PORT}"
    export all_proxy="socks5://${PROXY_HOST}:${SOCKS_PORT}"
    export no_proxy="$NO_PROXY"

    echo -e "${YELLOW}正在启用代理并测试连接...${NC}"
    echo -e "HTTP 代理: http://${PROXY_HOST}:${HTTP_PORT}"
    echo -e "SOCKS5 代理: socks5://${PROXY_HOST}:${SOCKS_PORT}"

    # 测试HTTP代理
    _test_connection "$TEST_URL" "http" "${PROXY_HOST}:${HTTP_PORT}"

    # 测试SOCKS5代理
    _test_connection "$TEST_URL" "socks5" "${PROXY_HOST}:${SOCKS_PORT}"

    _proxy_status_check
}

# 禁用代理
proxy_off() {
    unset http_proxy https_proxy all_proxy no_proxy

    echo -e "${YELLOW}正在关闭代理并测试直连...${NC}"

    # 测试直连
    _test_connection "$DIRECT_TEST_URL" ""

    _proxy_status_check
}

# 状态切换
proxy_toggle() {
    if [ -n "$http_proxy" ]; then
        proxy_off
    else
        proxy_on
    fi
}

# 帮助信息
proxy_help() {
    echo -e "${YELLOW}代理快捷命令:${NC}"
    echo -e "${YELLOW}当前配置:${NC}"
    echo -e "  代理地址: ${CYAN}${PROXY_HOST}${NC}"
    echo -e "  HTTP端口: ${CYAN}${HTTP_PORT}${NC}"
    echo -e "  SOCKS端口: ${CYAN}${SOCKS_PORT}${NC}"
    echo -e "  测试URL: ${CYAN}${TEST_URL}${NC}"
    echo -e "  直连测试URL: ${CYAN}${DIRECT_TEST_URL}${NC}"
}
EOF

三. 修改并更新~/.bashrc文件

1. 修改

cat >> ~/.bashrc <<'EOF'
# ====================== Shell 函数加载 ======================
# 加载函数自动加载器
if [ -f ~/.config/shell_functions/function_loader.sh ]; then
    source ~/.config/shell_functions/function_loader.sh
fi
EOF

2. 更新

source ~/.bashrc

四、测试函数

在终端执行以下命令:

# 开启代理
proxy_on
# 关闭代理
proxy_off
# 切换代理状态
proxy_toggle

网站公告

今日签到

点亮在社区的每一天
去签到