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

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"

方案说明

  1. 用awk扫描文件,精准识别[mysqld]段并完整收集其所有内容
  2. 单独收集[mysqld]之后的所有配置段和内容
  3. 按顺序输出:先输出[mysqld]之前的内容,再输出后续收集的内容,最后输出[mysqld]段
  4. 通过临时文件替换原文件,避免直接修改时的行号偏移或内容丢失问题

原脚本问题解析

  1. 数组赋值错误:declare -a LINE_CONTENT=$(sed ...)会把所有内容按空格分割成数组元素,空行和连续换行都会被丢弃,导致内容丢失
  2. 变量解析失败:sed命令使用单引号包裹,\${value}无法被解析为变量值,因此插入的是字符串而非实际内容
  3. 循环修改文件效率低:每次循环调用sed -i会重复修改文件,容易出现行号偏移,空行存在时问题更明显

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:37:39