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

Linux Shell下实现列转行并按IP分组生成CSV

按交换机IP分组转换为指定CSV格式

原始输入文件

192.168.0.35 GigabitEthernet0/19 AP-CISCO-02
192.168.0.35 GigabitEthernet0/20 AP-CISCO-12
192.168.0.36 GigabitEthernet0/12 AP-CISCO-70
192.168.0.36 GigabitEthernet0/20 AP-CISCO-71
192.168.0.40 GigabitEthernet1/0/22 AP-CISCO-73
192.168.0.254 GigabitEthernet2/47 AP-CISCO-19
192.168.0.254 GigabitEthernet3/37 AP-CISCO-86
192.168.0.254 GigabitEthernet3/38 AP-CISCO-85

目标CSV格式

要求将列转成行,并按第一列的交换机IP分组:第一行是去重后的交换机IP,第二行是对应IP下的接口合并结果,第三行是对应IP下的描述合并结果。

192.168.0.35, 192.168.0.36, 192.168.0.40, 192.168.0.254
"GigabitEthernet0/19, GigabitEthernet0/20", "GigabitEthernet0/12, GigabitEthernet0/20", "GigabitEthernet1/0/22", "GigabitEthernet2/47, GigabitEthernet3/37, GigabitEthernet3/38"
"AP-CISCO-02, AP-CISCO-12", "AP-CISCO-70, AP-CISCO-71", "AP-CISCO-73", "AP-CISCO-19, AP-CISCO-86, AP-CISCO-85"

最初尝试的awk代码及问题

尝试了以下awk代码:

awk '{
    for (f = 1; f <= NF; f++) {
        a[NR, f] = $f 
    } 
}

NF > nf { nf = NF }

END {
   for (f = 1; f <= nf; f++) {
       for (r = 1; r <= NR; r++) {
           printf "\""a[r, f]"\"" (r==NR ? RS : FS=",")
       }
   }
}' myfile

但输出不符合需求:IP重复出现,接口和描述也没有按IP分组合并,结果如下:

"192.168.0.35","192.168.0.35","192.168.0.36","192.168.0.36","192.168.0.40","192.168.0.254","192.168.0.254","192.168.0.254"
"GigabitEthernet0/19","GigabitEthernet0/20","GigabitEthernet0/12","GigabitEthernet0/20","GigabitEthernet1/0/22","GigabitEthernet2/47","GigabitEthernet3/37","GigabitEthernet3/38"
"AP-CISCO-02","AP-CISCO-12","AP-CISCO-70","AP-CISCO-71","AP-CISCO-73","AP-CISCO-19","AP-CISCO-86","AP-CISCO-85"

已实现的解决方案

我已经用awk实现了需求,代码如下:

{
    for (f = 1; f <= NF; f++) {
        a[NR, f] = $f 
    } 
}

NF > nf { nf = NF }

END {
 intlist="\""
 desclist="\""
 for (f = 1; f <= nf; f++) {
       for (r = 1; r <= NR; r++) {
           if (f==1) {
                if (a[r,1]!=a[r+1,1]) {
                    printf a[r,f] (r==NR ? RS="\n" : FS=",")
                }
           }
           
           if (f==2){
                if (r==1){
                    intlist=intlist""a[r,2]
                }
                else{
                    if (a[r,1]==a[r-1,1]) {
                        intlist=intlist", "a[r,2]
                    }
                    else {
                        printf intlist"\","
                        intlist="\""a[r,2] 
                    }
                }
                
                if (r==NR) {
                   printf intlist"\"\n"
                }
           }
           
           if (f==3){
                if (r==1){
                    desclist=desclist""a[r,3]
                }
                else{
                    if (a[r,1]==a[r-1,1]) {
                        desclist=desclist", "a[r,3]
                    }
                    else {
                        printf desclist"\","
                        desclist="\""a[r,3] 
                    }
                }
                
                if (r==NR) {
                   printf desclist"\""
                }
           }
       }
   }
}

更简洁的优化方案

可以用逻辑更清晰的awk写法,直接按IP分组存储接口和描述,最后统一输出:

awk '{
    ip[$1]
    ints[$1] = (ints[$1] ? ints[$1] ", " : "") $2
    descs[$1] = (descs[$1] ? descs[$1] ", " : "") $3
}
END {
    # 输出IP行
    sep = ""
    for (i in ip) {
        printf "%s%s", sep, i
        sep = ", "
    }
    print ""
    
    # 输出接口行
    sep = ""
    for (i in ip) {
        printf "%s\"%s\"", sep, ints[i]
        sep = ", "
    }
    print ""
    
    # 输出描述行
    sep = ""
    for (i in ip) {
        printf "%s\"%s\"", sep, descs[i]
        sep = ", "
    }
    print ""
}' myfile

这种写法避免了二维数组的复杂遍历,直接用数组按IP聚合数据,代码更易读维护。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:44:50