使用单条Awk命令实现多分隔符文本数据转置
问题
需要用单条Awk命令完成数据转换:现有文本文件的字段规则为前三个字段用冒号分隔,最后一个字段(主机列表)用空格分隔,格式为「唯一ID:名称:唯一标识符:主机列表(可空、可包含重复项)」。
输入文件内容:
sv_0:blabla:205700DD4C506261796ED3:Host_10 Host_1 Host_16 sv_111:abcd:205700DD4C50629585735C:Host_10 sv_3:xpto1:2057008E714F629B3BCDCF:Host_11 Host_10 sv_46:something:205700DD4C50629E5AB93A:
期望输出:
sv_0 blabla 205700DD4C506261796ED3 Host_10 sv_0 blabla 205700DD4C506261796ED3 Host_1 sv_0 blabla 205700DD4C506261796ED3 Host_16 sv_111 abcd 205700DD4C50629585735C Host_10 sv_3 xpto1 2057008E714F629B3BCDCF Host_11 sv_3 xpto1 2057008E714F629B3BCDCF Host_10 sv_46 something 205700DD4C50629E5AB93A
目前已通过两条Awk命令管道实现,但希望避免多管道操作,现有命令:
awk -F: '{print $1" "$2" "$3" "$4 }' file.txt | awk '{nfield=4; while (NF >= nfield) {print $1" "$2" "$3" "$nfield; nfield++}}'
单Awk命令实现方案
直接在Awk内部拆分主机列表字段,就能用单条命令完成转换,命令如下:
awk -F: '{ prefix = $1 " " $2 " " $3 n = split($4, hosts, / /) if (n == 0) { print prefix } else { for (i = 1; i <= n; i++) { if (hosts[i] != "") { print prefix " " hosts[i] } } } }' file.txt
关键逻辑说明
- 字段拆分:用
-F:把每行按冒号拆成4个字段,前三个字段拼接成固定前缀prefix。 - 主机列表拆分:用
split()函数把第四个字段按空格拆成数组hosts,拿到主机数量。 - 输出处理:
- 如果主机列表为空(
n=0),直接输出前缀; - 否则遍历数组,跳过空元素(避免原字段末尾空格导致的无效输出),逐个输出前缀加主机名。
- 如果主机列表为空(
这样就不需要管道,一条命令搞定所有转换。
内容的提问来源于stack exchange,提问作者tgreis
相关产品推荐
相关产品推荐

