如何在Bash中检测文件中是否存在重复的多行配置段
问题分析与解决方案
问题原因
你使用的grep -z "$section" file.txt存在两个关键问题:
- 子串匹配误判:grep默认是子串匹配,只要文件中包含
$section里的任意连续内容(比如某一行参数),就会返回匹配成功,无法识别完整的配置段。 - 格式干扰:如果
$section变量开头/结尾有多余空行(比如你提供的示例变量开头有换行),grep -z会匹配文件中配置段之间的空行,导致无论目标段是否存在,都判定为重复。
另外,-z选项会将文件换行符替换为NUL字符,和变量中保留的普通换行符格式不一致,进一步导致匹配误差。
解决方案
根据需求分两种场景提供可靠实现:
场景1:检查同名配置段(推荐)
只要配置段名称重复就判定为重复(无需关注参数内容),实现步骤如下:
# 从$section变量中提取配置段名称 section_name=$(echo "$section" | grep -oP 'section "\K[^"]+') # 检查文件中是否已存在同名配置段 if grep -q "section \"$section_name\"" file.txt; then echo "Duplicate found" else echo "$section" >> file.txt fi
场景2:检查完全相同的配置段
需要严格匹配配置段的所有内容(包括参数、缩进、格式),用awk实现精确匹配:
# 清理$section中的多余空行,避免格式干扰 clean_section=$(echo "$section" | sed '/^[[:space:]]*$/d') # 用awk逐行匹配整个配置段 if awk -v sec="$clean_section" ' BEGIN { n = split(sec, sec_lines, /\n/) if (n == 0) exit 1 } { if ($0 == sec_lines[current+1]) { current++ if (current == n) exit 0 } else { current = 0 } } END { exit 1 }' file.txt; then echo "Duplicate found" else echo "$clean_section" >> file.txt fi
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

