Bash环境下类JSON多行字符串的模式替换方案咨询——将df命令输出中的磁盘设备名替换为disk_n格式
实现磁盘设备名替换为disk_n格式:单awk命令即可搞定
当然可以用单个awk命令直接实现这个需求,不需要额外的循环遍历——这其实是最简洁高效的方案,我们可以在生成proto-json的awk逻辑里直接加入计数器,一次性完成设备名替换。
单awk命令修改方案
只需要修改你原有的PATTERN变量,在awk的BEGIN块里初始化一个计数器,每处理一行匹配的磁盘记录时,用计数器值替换原有的设备名,然后计数器自增即可。修改后的完整脚本如下:
# 新增BEGIN块初始化计数器,替换disk.device为disk_<序号> PATTERN='BEGIN {i=0} !/loop/ && /^\// {printf "\"disk.device\":\"disk_%d\",\"disk.mount\":\"%s\",\"disk.total\":%d,\"disk.used\":%d,\"disk.free\":%d,\"disk.percentage\":%.2f\n", i++, $6, $2, $2-$4, $4, ($2-$4)/($2+1)*100}' MODE="" NAME="disk.device" PAYLOAD="$(df -a | awk "$PATTERN")" jsonify.sh $MODE "$PAYLOAD"
逻辑说明:
BEGIN {i=0}:在awk开始处理输入前,初始化计数器i为0;- 每匹配到一行符合条件的磁盘记录(排除loop设备、以/开头的挂载点),就用
disk_%d格式输出计数器当前值,然后执行i++让计数器自增; - 其他字段的处理逻辑和你原来的完全一致,不需要改动。
这样生成的PAYLOAD直接就是替换后的proto-json格式,完全符合你的需求。
备选:显式循环实现方案
如果你因为某些原因需要用循环遍历已生成的PAYLOAD数据,也可以用bash的while read循环配合sed来逐行替换:
# 先保留你原来的PATTERN(不修改设备名) PATTERN='!/loop/ && /^\// {printf "\"disk.device\":\"%s\",\"disk.mount\":\"%s\",\"disk.total\":%d,\"disk.used\":%d,\"disk.free\":%d,\"disk.percentage\":%.2f\n", $1, $6, $2, $2-$4, $4, ($2-$4)/($2+1)*100}' MODE="" NAME="disk.device" PAYLOAD="$(df -a | awk "$PATTERN")" # 用循环逐行替换disk.device的值 count=0 processed_payload="" while read -r line; do # 用sed替换行中的disk.device值为disk_<count> new_line=$(echo "$line" | sed -E 's/"disk.device":"[^"]+"/"disk.device":"disk_'$count'"/') processed_payload+="$new_line"$'\n' ((count++)) done <<< "$PAYLOAD" # 传递处理后的payload给jsonify.sh jsonify.sh $MODE "$processed_payload"
逻辑说明:
- 先按原来的逻辑生成未替换的
PAYLOAD; - 初始化计数器
count为0,通过while read逐行读取PAYLOAD; - 用
sed的正则表达式匹配每一行中的"disk.device":"xxx"部分,替换为"disk.device":"disk_<count>"; - 收集处理后的每一行,最后传递给
jsonify.sh。
不过这种方案需要多一次循环和sed处理,效率不如直接在awk里完成替换,所以更推荐第一种单awk命令的方案。
内容的提问来源于stack exchange,提问作者darkpirate
相关产品推荐
相关产品推荐

