如何用sed仅删除完全匹配单词,排除含连字符的匹配项
解决DNS区域文件误删记录的问题
原sed命令误删带连字符的主机标签行,是因为\bsmtp\b会匹配行内任意位置的smtp(连字符属于非单词字符,会被当成单词边界)。要精确删除主机标签完全等于目标词的指定类型记录,可用以下两种方案:
方案1:改进sed命令
通过正则限定目标词必须是行首的完整第一列,再匹配记录类型:
- 删除A记录:
sed -ie "/^${target}\b.*\bA\b/d" "$zonefile" - 删除CNAME记录:
sed -ie "/^${target}\b.*\bCNAME\b/d" "$zonefile"
关键解释:
^${target}\b:确保目标词是行首的完整第一列(后面跟空格/制表符等分隔符),不会匹配test-smtp(行首是test-)或smtp5(smtp后是数字,不是单词边界)。\bA\b:匹配完整的记录类型,避免误匹配含A的其他字段。
方案2:awk按列精确匹配(推荐)
awk按列处理结构化文本,完全避免正则边界问题,更可靠:
- 删除A记录:
awk -v tgt="$target" '{if ($1 == tgt && $4 == "A") next} 1' "$zonefile" > temp && mv temp "$zonefile" - 删除CNAME记录:
awk -v tgt="$target" '{if ($1 == tgt && $4 == "CNAME") next} 1' "$zonefile" > temp && mv temp "$zonefile"
关键解释:
$1 == tgt:精确匹配第一列(主机标签)等于目标词,彻底杜绝部分匹配。$4 == "A":对应标准DNS区域文件的记录类型列(前3列是主机标签、TTL、类IN),如果你的文件省略TTL,改成$3即可。{next} 1:跳过匹配行,其他行正常输出,最后覆盖原文件。
脚本整合示例
把逻辑整合到你的my_script中:
#!/bin/bash if [ $# -ne 3 ]; then echo "用法: $0 [-a|-c] <目标主机标签> <区域文件>" exit 1 fi case "$1" in -a) RECORD_TYPE="A" ;; -c) RECORD_TYPE="CNAME" ;; *) echo "无效参数,使用 -a 或 -c"; exit 1 ;; esac TARGET="$2" ZONE_FILE="$3" # 使用awk方案(推荐) awk -v tgt="$TARGET" -v type="$RECORD_TYPE" '{if ($1 == tgt && $4 == type) next} 1' "$ZONE_FILE" > temp.$$ && mv temp.$$ "$ZONE_FILE"
执行./my_script -a smtp sampledomainzone.com就只会删除主机标签为smtp的A记录,不会误删test-smtp、smtp-dev等行。
内容的提问来源于stack exchange,提问作者humbleStrength
相关产品推荐
相关产品推荐

