MySQL配置文件脚本问题:将[mysqld]下方内容移至其上方
修复MySQL配置文件内容迁移的Bash脚本问题
需求说明
需要将MySQL配置文件my.cnf中[mysqld]段下方的所有配置段及其内容移至[mysqld]段上方,并删除原位置的对应内容。
现有脚本问题
现有脚本存在两个核心问题:
- 插入内容时仅输出变量名
${value}而非实际内容 - 配置文件存在空行时,仅能复制部分内容,无空行时才可正常运行
现有脚本代码
#!/bin/bash FILENAME='my.cnf' LINE_NUMBER1=$1 LINE_NUMBER2=$2 declare -a LINE_CONTENT=$(sed -n "${LINE_NUMBER1},${LINE_NUMBER2}"p "$FILENAME") sed -i "${LINE_NUMBER1},${LINE_NUMBER2}"'d' "$FILENAME" for value in "${LINE_CONTENT[@]}"; do sed -i "/^#/n;/\[mysqld]/i \${value}" "$FILENAME" done
配置文件示例
当前my.cnf内容
[client] a=99 [mysqld] b=1 c=2 [myisamchk] a=1,2 d=22 e=name [sst] f=yes
预期执行后内容
[client] a=99 [myisamchk] a=1,2 d=22 e=name [sst] f=yes [mysqld] b=1 c=2
实际异常表现
当配置文件包含空行时,脚本仅能复制部分内容(如仅保留[mysqld]及第一行配置);无空行时可正常运行。
正确解决方案
推荐使用awk处理这类分段的配置文件,逻辑更清晰且能完美处理空行:
#!/bin/bash FILENAME='my.cnf' awk ' # 标记找到[mysqld]段并收集其内容 /\[mysqld]/ { mysqld_found = 1 mysqld_block = "" # 读取整个[mysqld]段的内容,直到下一个配置段开头 while (getline && $0 !~ /^\[.*\]/) { mysqld_block = mysqld_block $0 "\n" } # 将下一个配置段的开头放回缓冲区 if ($0 ~ /^\[.*\]/) { ungetline } next } # 收集[mysqld]之后的所有内容 mysqld_found { after_mysqld = after_mysqld $0 "\n" next } # 输出[mysqld]之前的内容 { print } # 最后输出后续内容和[mysqld]段 END { printf "%s[mysqld]\n%s", after_mysqld, mysqld_block } ' "$FILENAME" > "${FILENAME}.tmp" && mv "${FILENAME}.tmp" "$FILENAME"
方案说明
- 用
awk扫描文件,精准识别[mysqld]段并完整收集其所有内容 - 单独收集
[mysqld]之后的所有配置段和内容 - 按顺序输出:先输出
[mysqld]之前的内容,再输出后续收集的内容,最后输出[mysqld]段 - 通过临时文件替换原文件,避免直接修改时的行号偏移或内容丢失问题
原脚本问题解析
- 数组赋值错误:
declare -a LINE_CONTENT=$(sed ...)会把所有内容按空格分割成数组元素,空行和连续换行都会被丢弃,导致内容丢失 - 变量解析失败:sed命令使用单引号包裹,
\${value}无法被解析为变量值,因此插入的是字符串而非实际内容 - 循环修改文件效率低:每次循环调用
sed -i会重复修改文件,容易出现行号偏移,空行存在时问题更明显
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

