Linux运维——Shell脚本读取配置文件
Shell脚本读取配置文件
- 一、键值对格式配置文件(最常用)
- 1.1、配置文件示例
- 1.2、source命令导入
- 1.3、sed解析
- 1.4、解析数组
- 二、INI格式配置文件
- 1.1、配置文件示例
- 1.2、sed解析
- 1.3、ini配置带数组(显式声明数组)
- 1.4、ini配置带数组(逗号分隔数组)
- 三、Yaml格式配置文件
- 3.1、配置文件示例
- 3.2、安装yq工具
- 3.3、使用yq工具解析
- 3.4、使用python的PyYAML库
- 四、JSON格式配置文件
- 4.1、配置文件示例
- 4.2、安装jq
- 4.3、jq读取配置脚本
- 4.4、Python的json模块解析
- 五、环境变量文件(.env格式)
- 5.1、配置文件示例
- 5.2、source加载
- 5.3、逐行解析(更安全)
- 5.4、完整案例(生产级实现)
一、键值对格式配置文件(最常用)
1.1、配置文件示例
config.cfg
# 这是注释
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASS=password123
DEBUG_MODE=true
1.2、source命令导入
#!/bin/bash
# 直接source导入(简单但需确保配置文件安全)
source config.cfg# 使用配置
echo "数据库主机: $DB_HOST"
echo "数据库端口: $DB_PORT"
直接使用source加载配置可能存在问题,更好的办法是进行签名或哈希校验再加载:
#!/bin/bash#检查文件签名或哈希
expected_hash="45626d89c487f717fedfd769bce914f1eb7e73fccb341544aa7645af4b41945d"
actual_hash=$(sha256sum config.cfg | cut -d' ' -f1)if [[ "$expected_hash" != "$actual_hash" ]]; thenecho "错误:配置文件哈希不匹配"exit 1
fisource config.cfgecho $DB_HOST
echo $DB_PORT
1.3、sed解析
#!/bin/bash# sed解析
while IFS='=' read -r key value; do# 跳过注释和空行[[ "$key" =~ ^#.*$ ]] || [[ -z "$key" ]] && continue# 去除可能的空格和引号key=$(echo $key | tr -d '[:space:]')value=$(echo $value | tr -d '[:space:]' | sed "s/^['\"]//;s/['\"]$//")# 赋值给变量declare "$key=$value"
done < config.cfg# 使用配置
echo "数据库主机: $DB_HOST"
echo "数据库端口: $DB_PORT"
1.4、解析数组
配置文件示例(config.txt):
# 应用配置
APP_NAME="MyApp"
APP_VERSION=1.0.0# 逗号分隔的数组
ADMIN_USERS="user1,user2,user3"
ALLOWED_IPS="192.168.1.1,192.168.1.2,10.0.0.1"
FEATURES="auth,logging,dashboard,api"
读取脚本:
#!/bin/bash# 加载配置文件函数
load_csv_config() {local config_file="$1"# 检查文件是否存在[ -f "$config_file" ] || { echo "错误: 配置文件不存在"; exit 1; }# 逐行处理配置文件while IFS='=' read -r key value; do# 跳过注释和空行[[ "$key" =~ ^#.*$ ]] || [[ -z "$key" ]] && continue# 去除键和值的首尾空格key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')# 去除值两端的引号value=${value%\"}value=${value#\"}# 检查是否是逗号分隔的值if [[ "$value" == *,* ]]; then# 临时修改IFS来分割数组local IFS=','# 读取为数组read -ra array <<< "$value"# 恢复默认IFSunset IFS# 创建数组变量declare -ag "${key}=(${array[*]})"else# 普通变量赋值declare -g "$key=$value"fidone < "$config_file"
}# 加载配置文件
load_csv_config "config.txt"# 使用配置
echo "应用名称: $APP_NAME"
echo "应用版本: $APP_VERSION"echo -e "\n管理员用户:"
printf " - %s\n" "${ADMIN_USERS[@]}"echo -e "\n允许的IP地址:"
printf " - %s\n" "${ALLOWED_IPS[@]}"echo -e "\n功能特性:"
echo "${FEATURES[@]}"
二、INI格式配置文件
1.1、配置文件示例
app.ini
[database]
host=127.0.0.1
port=3306
user=root
password=secret[application]
debug=true
log_level=warning
1.2、sed解析
#!/bin/bash# 使用awk解析INI文件
parse_ini() {local ini_file="$1"local section=""while IFS= read -r line; doline=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')# 跳过注释和空行[[ -z "$line" ]] || [[ "$line" =~ ^\; ]] || [[ "$line" =~ ^\# ]] && continue# 处理节头if [[ "$line" =~ ^\[(.*)\]$ ]]; thensection="${BASH_REMATCH[1]}"# 处理键值对elif [[ "$line" =~ ^([^=]+)=(.*)$ ]]; thenkey="${BASH_REMATCH[1]}"value="${BASH_REMATCH[2]}"# 去除首尾空格key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')# 创建变量名 SECTION_KEYif [[ -n "$section" ]]; thenvar_name="${section}_${key}"elsevar_name="$key"fi# 赋值declare -g "$var_name=$value"fidone < "$ini_file"
}parse_ini "app.ini"# 使用配置
echo "数据库主机: ${database_host}"
echo "应用日志级别: ${application_log_level}"
echo $application_debug
1.3、ini配置带数组(显式声明数组)
app1.ini
[application]
name = My Application
version = 1.2.3[arrays]
admin_users[] = admin1
admin_users[] = admin2
admin_users[] = admin3allowed_ips[] = 192.168.1.1
allowed_ips[] = 192.168.1.2
allowed_ips[] = 10.0.0.1config_paths[] = /etc/app/config.d
config_paths[] = /var/lib/app/config
config_paths[] = ~/.app/config
#!/bin/bash# 声明关联数组存储配置
declare -A config
declare -a admin_users allowed_ips config_paths# 解析INI文件函数
parse_ini() {local ini_file="$1"local current_section=""[ -f "$ini_file" ] || { echo "错误: 文件不存在"; return 1; }while IFS= read -r line; do# 移除注释和空格line="${line%%[;#]*}" # 移除注释line="${line##[[:space:]]}" # 移除前导空格line="${line%%[[:space:]]}" # 移除尾部空格# 跳过空行[ -z "$line" ] && continue# 处理节(section)if [[ "$line" =~ ^\[(.+)\]$ ]]; thencurrent_section="${BASH_REMATCH[1]}"continuefi# 处理数组元素 匹配以某些字符开头[]结尾的即keyif [[ "$line" =~ ^([^[:space:]=]+)\[\] ]]; thenlocal array_name="${BASH_REMATCH[1]}"local value="${line#*=[[:space:]]}"value="${value%%[[:space:]]}"# 去除值两端的引号value="${value%\"}"value="${value#\"}"value="${value%\'}"value="${value#\'}"# 处理波浪线路径扩展if [[ "$value" =~ ^~ ]]; thenvalue="${value/#\~/$HOME}"fi# 根据数组名称添加到对应数组case "$array_name" in"admin_users") admin_users+=("$value") ;;"allowed_ips") allowed_ips+=("$value") ;;"config_paths") config_paths+=("$value") ;;esaccontinuefi# 处理普通键值对if [[ "$line" =~ ^([^[:space:]=]+)[[:space:]]*=[[:space:]]*(.*)$ ]]; thenlocal key="${BASH_REMATCH[1]}"local value="${BASH_REMATCH[2]}"# 去除值两端的引号value="${value%\"}"value="${value#\"}"value="${value%\'}"value="${value#\'}"# 存储到关联数组if [ -n "$current_section" ]; thenconfig["${current_section}.${key}"]="$value"elseconfig["${key}"]="$value"fifidone < "$ini_file"
}# 使用示例
parse_ini "app1.ini"# 访问配置值
echo "应用名称: ${config[application.name]}"
echo "应用版本: ${config[application.version]}"# 访问数组配置
echo -e "\n管理员用户:"
printf " - %s\n" "${admin_users[@]}"echo -e "\n允许的IP地址:"
printf " - %s\n" "${allowed_ips[@]}"echo -e "\n配置路径:"
printf " - %s\n" "${config_paths[@]}"
echo "${config_paths[@]}"# 验证路径是否存在
echo -e "\n验证配置路径是否存在:"
for path in "${config_paths[@]}"; doif [ -e "$path" ]; thenecho " [存在] $path"elseecho " [不存在] $path"fi
done
1.4、ini配置带数组(逗号分隔数组)
配置文件app2.ini
[application]
name = My Application
version = 1.2.3[arrays]
admin_users = admin1,admin2,admin3allowed_ips = 192.168.1.1,192.168.1.2,10.0.0.1config_paths = /etc/app/config.d,/var/lib/app/config,~/.app/config
解析app2.sh
#!/bin/bash# 声明关联数组存储配置
declare -A config
declare -a admin_users allowed_ips config_paths# 解析INI文件函数
parse_ini() {local ini_file="$1"local current_section=""[ -f "$ini_file" ] || { echo "错误: 文件不存在"; return 1; }while IFS= read -r line; do# 移除注释和空格line="${line%%[;#]*}" # 移除注释line="${line##[[:space:]]}" # 移除前导空格line="${line%%[[:space:]]}" # 移除尾部空格# 跳过空行[ -z "$line" ] && continue# 处理节(section)if [[ "$line" =~ ^\[(.+)\]$ ]]; thencurrent_section="${BASH_REMATCH[1]}"continuefi# 处理键值对if [[ "$line" =~ ^([^[:space:]=]+)[[:space:]]*=[[:space:]]*(.*)$ ]]; thenlocal key="${BASH_REMATCH[1]}"local value="${BASH_REMATCH[2]}"# 去除值两端的引号value="${value%\"}"value="${value#\"}"value="${value%\'}"value="${value#\'}"# 处理波浪线路径扩展if [[ "$value" =~ ^~ ]]; thenvalue="${value/#\~/$HOME}"fi# 存储到关联数组if [ -n "$current_section" ]; thenconfig["${current_section}.${key}"]="$value"elseconfig["${key}"]="$value"fi# 处理逗号分隔的数组if [[ "$value" == *,* ]]; thencase "$key" in"admin_users")IFS=',' read -ra admin_users <<< "$value";;"allowed_ips")IFS=',' read -ra allowed_ips <<< "$value";;"config_paths")IFS=',' read -ra config_paths <<< "$value"# 处理路径中的波浪线for i in "${!config_paths[@]}"; doif [[ "${config_paths[i]}" =~ ^~ ]]; thenconfig_paths[i]="${config_paths[i]/#\~/$HOME}"fidone;;esacfifidone < "$ini_file"
}# 使用示例
parse_ini "app2.ini"# 访问配置值
echo "应用名称: ${config[application.name]}"
echo "应用版本: ${config[application.version]}"# 访问数组配置
echo -e "\n管理员用户:"
printf " - %s\n" "${admin_users[@]}"echo -e "\n允许的IP地址:"
printf " - %s\n" "${allowed_ips[@]}"echo -e "\n配置路径:"
printf " - %s\n" "${config_paths[@]}"# 验证路径是否存在
echo -e "\n验证配置路径是否存在:"
for path in "${config_paths[@]}"; doif [ -e "$path" ]; thenecho " [存在] $path"elseecho " [不存在] $path"fi
done# 验证IP地址格式
echo -e "\n验证IP地址格式:"
for ip in "${allowed_ips[@]}"; doif [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; thenecho " [有效] $ip"elseecho " [无效] $ip"fi
done
三、Yaml格式配置文件
3.1、配置文件示例
config.yaml
application:name: My Applicationversion: 1.2.3database:host: localhostport: 3306credentials:username: adminpassword: secret123features:- logging- auth- api
3.2、安装yq工具
yq是一个强大的YAML处理工具,类似于jq但专门用于YAML。
# 使用pip安装
pip install yq# 或者使用包管理器
# Ubuntu/Debian
sudo apt-get install yq# CentOS/RHEL
sudo yum install yq# macOS
brew install yq
3.3、使用yq工具解析
#!/bin/bash# 读取简单值
app_name=$(yq e '.application.name' config.yaml)
app_version=$(yq e '.application.version' config.yaml)# 读取嵌套值
db_host=$(yq e '.database.host' config.yaml)
db_port=$(yq e '.database.port' config.yaml)# 读取数组
features=$(yq e '.features[]' config.yaml)# 输出结果
echo "应用名称: $app_name"
echo "应用版本: $app_version"
echo "数据库主机: $db_host"
echo "数据库端口: $db_port"
echo "功能特性:"
echo "$features" | while read -r feature; doecho " - $feature"
done
3.4、使用python的PyYAML库
如果系统中有Python,可以使用PyYAML库解析YAML。
#!/bin/bash# 使用Python解析YAML
parse_yaml() {python3 -c "
import yaml
import syswith open('$1') as f:config = yaml.safe_load(f)# 输出为Shell变量格式def print_items(d, prefix=''):for k, v in d.items():if isinstance(v, dict):print_items(v, f'{prefix}{k}_')else:print(f'{prefix}{k}=\"{v}\"')print_items(config)
"
}# 加载配置
eval "$(parse_yaml config.yaml)"# 使用配置
echo "应用名称: $application_name"
echo "应用版本: $application_version"
echo "数据库主机: $database_host"
echo "数据库端口: $database_port"
echo "数据库用户名: $database_credentials_username"
四、JSON格式配置文件
4.1、配置文件示例
config.json
{"application": {"name": "My App","version": "1.2.3","debug": false},"database": {"host": "localhost","port": 3306,"credentials": {"username": "admin","password": "secret123"}},"features": ["logging", "auth", "api"]
}
4.2、安装jq
jq是一个强大的命令行JSON处理器,非常适合处理JSON配置文件。
# Ubuntu/Debian
sudo apt-get install jq# CentOS/RHEL
sudo yum install jq# macOS
brew install jq
4.3、jq读取配置脚本
#!/bin/bash# 检查jq是否安装
if ! command -v jq &> /dev/null; thenecho "错误: 需要安装jq工具"exit 1
fi# 检查配置文件是否存在
if [ ! -f "config.json" ]; thenecho "错误: 配置文件config.json不存在"exit 1
fi# 读取简单值
app_name=$(jq -r '.application.name' config.json)
app_version=$(jq -r '.application.version' config.json)
debug_mode=$(jq -r '.application.debug' config.json)# 读取嵌套值
db_host=$(jq -r '.database.host' config.json)
db_port=$(jq -r '.database.port' config.json)
db_user=$(jq -r '.database.credentials.username' config.json)# 读取数组到Bash数组
mapfile -t features < <(jq -r '.features[]' config.json)# 输出结果
echo "应用配置:"
echo " 名称: $app_name"
echo " 版本: $app_version"
echo " 调试模式: $debug_mode"
echo "数据库配置:"
echo " 主机: $db_host"
echo " 端口: $db_port"
echo " 用户名: $db_user"
echo "功能特性:"
for feature in "${features[@]}"; doecho " - $feature"
done
4.4、Python的json模块解析
如果系统中有Python,可以使用Python的标准库json来解析JSON文件。
#!/bin/bash# 使用Python解析JSON
parse_json() {python3 -c "
import json
import syswith open('$1') as f:config = json.load(f)# 输出为Shell变量格式def print_items(d, prefix=''):for k, v in d.items():if isinstance(v, dict):print_items(v, f'{prefix}{k}_')elif isinstance(v, list):print(f'{prefix}{k}=(')for item in v:print(f'\"{item}\"')print(')')else:print(f'{prefix}{k}=\"{v}\"')print_items(config)
"
}# 加载配置
eval "$(parse_json config.json)"# 使用配置
echo "应用名称: $application_name"
echo "应用版本: $application_version"
echo "调试模式: $application_debug"
echo "数据库主机: $database_host"
echo "数据库端口: $database_port"
echo "数据库用户名: $database_credentials_username"
echo "功能特性:"
for feature in "${features[@]}"; doecho " - $feature"
done
五、环境变量文件(.env格式)
5.1、配置文件示例
config.env
# 应用配置
APP_NAME="My Application"
APP_VERSION=1.2.3
DEBUG=true# 数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_USER=admin
DB_PASS="secret123"# 路径配置
LOG_DIR=/var/log/myapp
CONFIG_DIR="/etc/myapp/config"
5.2、source加载
#!/bin/bash# 检查.env文件是否存在
if [ ! -f ".env" ]; thenecho "错误: .env文件不存在"exit 1
fi# 方法1:直接source导入(注意安全问题)
set -a # 自动导出所有变量
source .env
set +a # 关闭自动导出# 使用配置
echo "应用名称: $APP_NAME"
echo "应用版本: $APP_VERSION"
echo "调试模式: $DEBUG"
echo "数据库主机: $DB_HOST"
echo "数据库端口: $DB_PORT"
echo "日志目录: $LOG_DIR"
echo "配置目录: $CONFIG_DIR"# 验证路径是否存在
if [ ! -d "$LOG_DIR" ]; thenecho "警告: 日志目录不存在 - $LOG_DIR"
fi
5.3、逐行解析(更安全)
#!/bin/bash# 安全的.env文件解析函数
load_dotenv() {local env_file="$1"# 检查文件是否存在且可读if [ ! -f "$env_file" ] || [ ! -r "$env_file" ]; thenecho "错误: 无法访问.env文件"return 1fi# 逐行处理.env文件while IFS= read -r line; do# 跳过注释和空行[[ "$line" =~ ^[[:space:]]*# ]] && continue[[ -z "$line" ]] && continue# 处理变量赋值if [[ "$line" =~ ^([[:alnum:]_]+)=(.*)$ ]]; thenlocal var_name="${BASH_REMATCH[1]}"local var_value="${BASH_REMATCH[2]}"# 去除值两端的引号var_value="${var_value%\"}"var_value="${var_value#\"}"var_value="${var_value%\'}"var_value="${var_value#\'}"# 设置变量declare -g "$var_name"="$var_value"export "$var_name"fidone < "$env_file"
}# 加载.env文件
load_dotenv ".env"echo "应用名称: $APP_NAME"
echo "应用版本: $APP_VERSION"
echo "调试模式: $DEBUG"
echo "数据库主机: $DB_HOST"
echo "数据库端口: $DB_PORT"
echo "日志目录: $LOG_DIR"
echo "配置目录: $CONFIG_DIR"# 验证路径是否存在
if [ ! -d "$LOG_DIR" ]; thenecho "警告: 日志目录不存在 - $LOG_DIR"
fi
5.4、完整案例(生产级实现)
#!/bin/bash# 安全的.env文件加载函数
load_dotenv_safe() {local env_file="$1"local line var_name var_value# 检查文件是否存在if [ ! -f "$env_file" ]; thenecho "错误: .env文件不存在" >&2return 1fi# 检查文件权限if [ "$(stat -c %a "$env_file")" -gt 600 ]; thenecho "警告: .env文件权限过于开放" >&2fi# 逐行处理while IFS= read -r line; do# 跳过注释和空行[[ "$line" =~ ^[[:space:]]*# ]] && continue[[ -z "${line// }" ]] && continue# 验证变量名格式if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; thenvar_name="${BASH_REMATCH[1]}"var_value="${BASH_REMATCH[2]}"# 去除值两端的引号var_value="${var_value%\"}"var_value="${var_value#\"}"var_value="${var_value%\'}"var_value="${var_value#\'}"# 设置变量declare -g "$var_name"="$var_value"export "$var_name"elseecho "警告: 忽略无效的变量赋值 - $line" >&2fidone < "$env_file"# 验证必需变量local required_vars=("APP_NAME" "DB_HOST" "DB_PORT")for var in "${required_vars[@]}"; doif [ -z "${!var}" ]; thenecho "错误: 必需变量 $var 未设置" >&2return 1fidone
}# 加载.env文件
load_dotenv_safe ".env" || exit 1# 设置默认值
: ${DEBUG:=false}
: ${LOG_DIR:=/var/log/myapp}# 使用配置
echo "应用配置:"
echo " 名称: $APP_NAME"
echo " 版本: $APP_VERSION"
echo " 调试模式: $DEBUG"
echo "数据库配置:"
echo " 主机: $DB_HOST"
echo " 端口: $DB_PORT"
echo " 用户: $DB_USER"
echo "路径配置:"
echo " 日志目录: $LOG_DIR"
echo " 配置目录: $CONFIG_DIR"# 验证路径
if [ ! -d "$LOG_DIR" ]; thenecho "创建日志目录: $LOG_DIR"mkdir -p "$LOG_DIR" || {echo "错误: 无法创建日志目录" >&2exit 1}
fi
相关文章:
Linux运维——Shell脚本读取配置文件
Shell脚本读取配置文件 一、键值对格式配置文件(最常用)1.1、配置文件示例1.2、source命令导入1.3、sed解析1.4、解析数组 二、INI格式配置文件1.1、配置文件示例1.2、sed解析1.3、ini配置带数组(显式声明数组)1.4、ini配置带数组…...

答题pk小程序道具卡的获取与应用
道具卡是答题PK小程序中必不可少的一项增加趣味性的辅助应用,那么道具卡是如何获取与应用的呢,接下来我们来揭晓答案: 一、道具卡的获取: 签到获取:在每日签到中签到不仅可获得当日的签到奖励积分,同时连…...

leetcode3265. 统计近似相等数对 I-medium
1 题目:统计近似相等数对 I 官方标定难度:中 给你一个正整数数组 nums 。 如果我们执行以下操作 至多一次 可以让两个整数 x 和 y 相等,那么我们称这个数对是 近似相等 的: 选择 x 或者 y 之一,将这个数字中的两个…...

【架构篇】代码组织结构设计
代码组织结构设计:模块化分层与高效协作实践 摘要 本文以Java项目为例,解析后端代码组织的标准化结构,涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 一、模块化设计的核心…...
2_Spring【IOC容器中获取组件Bean】
Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…...

日期数据渲染转换问题
今天在学习Springboot框架时,想做一个非常简单的增删改查巩固一下,结果在数据渲染上出现了一个小问题,如图数据库中的数据一切正常 但是在前端渲染时,是下面这个效果 这是因为数据库存储的日期类型数据在前端渲染时,没…...
Spring Boot拦截器详解:原理、实现与应用场景
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、拦截器概述 拦截器(Interceptor)是Spring MVC框架中用于对请求进行预处理和后处理的组件,主要作用于Controller层。相…...

ubuntu18.04编译qt5.14.2源码
ubuntu18.04编译qt5.14.2源码 文章目录 ubuntu18.04编译qt5.14.2源码[toc]1 前言2 参考文档3 下载源码3.1 方法13.2 方法23.3 方法3 4 ubuntu编译qt源码4.1 环境准备4.2 设置交换分区大小4.3 编译源码4.4 添加环境变量4.5 验证编译结果4.6 编译帮助文档(qch…...

创建指定版本的vite项目
1、获取vite的版本号 npm view create-vite versions 注:4.4.1版本即对应着node16版本的项目 2、创建制定版本的vite项目 npm init vite<version>...

iOS 初识RunLoop
iOS 初识RunLoop 文章目录 iOS 初识RunLoopRunLoop的概念RunLoop的功能RunLoop和线程的关系RunLoop的结构ModeObserverTimer 和 source小结 RunLoop的核心RunLoop的流程RunLoop的应用AutoreleasePool响应触控事件刷新界面常驻线程网络请求NSTimer 和 CADisplayLinkNSTimerGCDTi…...

电子电路仿真实验教学平台重磅上线!——深圳航天科技创新研究院倾力打造,助力高校教学数字化转型
在传统电子电路课堂中,实验室的灯光总与高昂的成本、拥挤的设备、反复的耗材损耗相伴,而教师不得不面对这样的现实:有限的硬件资源束缚着教学深度,不可逆的实验风险制约着创新探索,固化的时空场景阻碍着个性化学习。当…...

搭建一个WordPress网站需要多少成本
WordPress 最初可能只是一个简单的博客平台。但近年来,它不仅成为了最好的博客平台,还成为了一个全面的内容管理系统。白宫、jQuery、NGINX、《纽约时报》等企业都把 WordPress 作为自己的网上家园。 不过,它们只是其中的佼佼者。根据 Built…...

Python数据可视化 - Pyecharts绘图示例
文章目录 一、Pyecharts简介及安装1. Pyecharts简介2. 安装Pyecharts 二、准备数据三、饼图示例1. 初始化选项配置2. 饼图相关设置3. 全局配置项3.1 标题配置项3.2 图例配置项3.3 提示框配置项3.4 工具箱配置项3.5 视觉映射配置项 4. 系列配置项4.1 标签选项配置4.2 图元样式配…...

NC016NC017美光固态芯片NC101NC102
NC016NC017美光固态芯片NC101NC102 在存储技术的演进历程中,美光科技的NC016、NC017、NC101与NC102系列固态芯片,凭借其技术创新与市场适应性,成为行业关注的焦点。本文将从技术内核、产品性能、行业动向、应用场景及市场价值五个维度&#…...

[Android] 青木扫描全能文档3.0,支持自动扫描功能
声明:根据许多帖友的反馈,我也根据重新实测得出结论:该app是提供一天的体验时间,后续还是采取收费才能使用功能的措施。因为现在市面上免费使用的扫描工具很少了,所以当初我初步测试感觉软件不错就发布了出来ÿ…...
Vue 3 动态 ref 的使用方式(表格)
一、问题描述 先给大家简单介绍一下问题背景。我正在开发的项目中,有一个表格组件,其中一列是分镜描述,需要支持视频上传功能。用户可以为每一行的分镜描述上传对应的视频示例。然而,在实现过程中,出现了一个严重的问…...
Bash fork 炸弹 —— :(){ :|: };:
🧠 什么是 Fork 炸弹? Fork 炸弹是一种拒绝服务(DoS)攻击技术,利用操作系统的 fork() 系统调用不断创建新进程,直到系统资源(如进程表、CPU、内存)被耗尽,从而使系统无法…...
互联网大厂Java面试:从Spring Boot到微服务架构的技术深挖
场景描述 在某互联网大厂的面试会议室里,严肃的面试官老王正审视着面前的程序员明哥。这场面试以业务场景为切入点,围绕Java技术栈展开。 第一轮:基础知识与Spring生态 面试官老王: 明哥,你对Spring Boot的核心功能…...
IT审计之外包
外包管理的定义与重要性 外包管理是指企业将部分业务或服务委托给外部供应商进行管理和执行的过程。在IT领域,外包管理尤为重要,因为IT系统的复杂性和关键性要求企业必须确保外包服务的质量和安全性。外包管理不仅涉及合同管理,还包括供应商…...
精益数据分析(66/126):技术驱动的大规模用户调研——从工具组合到高效验证
精益数据分析(66/126):技术驱动的大规模用户调研——从工具组合到高效验证 在创业的移情阶段,如何突破小规模访谈的局限,快速获取大规模用户反馈?今天,我们结合LikeBright的实战案例与《精益数…...

通俗解释Transformer在处理序列问题高效的原因(个人理解)
Transformer出现的背景 CNN 的全局关联缺陷卷积神经网络(CNN)通过多层堆叠扩大感受野,但在自然语言处理中存在本质局限: 局部操作的语义割裂:每个卷积核仅处理固定窗口(如 3-5 词),…...
第12章 Java多线程机制
12.1 进程与线程 4种状态:新建、运行、中断和死亡。 (新建、运行、中断和死亡) 建立线程的两种方法:用Thread类或其子类。 线程新建后,必须调用 start () 方法使其进入就绪队列,才有机会获得 CPU 资源&a…...

区间带边权并查集,XY4060泄露的测试点
目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 码蹄集 二、解题报告 1、思路分析 关于带边权并查集:并查集&…...

【数据结构】1-4算法的空间复杂度
数据结构知识点合集 知识点 空间复杂度的定义以及计算 空间复杂度--空间开销(内存开销)与问题规模 n 之间的关系 无论问题规模怎么变,算法运行所需的内存空间都是固定的常量,算法空间复杂度为S(n) O(1),S 表示 “Spac…...
nt!ExRemoveHeadNBQueue 函数分析
第一部分: 1: kd> p nt!MmMapLockedPagesSpecifyCache0x20f: 80a98491 e8ecb00500 call nt!ExRemoveHeadNBQueue (80af3582) 1: kd> t nt!ExRemoveHeadNBQueue: 80af3582 55 push ebp 1: kd> dv Header 0x89be5008 …...

OpenAI推出Codex — ChatGPT内置的软件工程Agents
OpenAI继续让ChatGPT对开发者更加实用。 几天前,他们增加了连接GitHub仓库的支持,可以"Deep Research"并根据你自己的代码提问。 今天,该公司在ChatGPT中推出了Codex的研究预览版,这是迄今为止最强大的AI编码Agent。 它可以编写代码、修复错误、运行测试,并在…...

AI日报 · 2025年5月15日|GPT-4.1 登陆 ChatGPT
AI日报 2025年5月15日|GPT-4.1 登陆 ChatGPT 1、OpenAI 在 ChatGPT 全面开放 GPT-4.1 与 GPT-4.1 mini 北京时间 5 月 14 日晚,OpenAI 在官方 Release Notes 中宣布:专为复杂代码与精细指令场景打造的 GPT-4.1 正式加入 ChatGPT࿰…...

W5500使用ioLibrary库创建TCP客户端
1、WIZnet全硬件TCP/IP协议栈 WIZnet全硬件TCP/IP协议栈,支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE协议。 以太网:支持BSD和WIZCHIP(W5500/W5300/W5200/W5100/W5100S)的SOCKET APIs驱动程序。 互联网: DHCP客户端 DNS客户端 FTP客…...
SQL练习(12/81)
目录 1.找类别最高值 使用子查询 使用窗口函数(MySQL8.X支持) 扩展:查找类别前N高的值 2.删除重复值并保留最小序号 delete实现 筛选无重复且序号最小值 select——where in select——join&子查询 3.找带条件的连续值 窗口函数…...

组态王|如何创建组态王工程?
哈喽,你好啊,我是雷工! 组态王是比较普及的组态软件之一,大部分工控人应该都接触过组态王软件, 最近有个用组态王软件开发上位机,对设备进行集中控制的项目,边开发,顺便记录一些使用方法。 本篇从基础的如何创建组态王工程开始记录,以下为操作笔记。 1 、首先在工程…...