bash脚本如何将带有密钥的日志转换为csv

bash脚本如何将带有密钥的日志转换为csv,bash,csv,Bash,Csv,我有一个表格格式的日志 ge-1/0/0.0 up down inet 10.100.100.1/24 multiservice ge-1/0/2.107 up up inet 10.187.132.193/27 10.187.132.194/27

我有一个表格格式的日志

ge-1/0/0.0              up    down inet     10.100.100.1/24 
                                   multiservice
ge-1/0/2.107            up    up   inet     10.187.132.193/27
                                            10.187.132.194/27
                                   multiservice
ge-1/1/4                up    up  
ge-1/1/5.0              up    up   inet     10.164.69.209/30
                                   iso     
                                   mpls    
                                   multiservice
我们如何将其转换为csv格式,如下所示:

ge-1/0/0.0,up,down,inet|multiservice,10.100.100.1/24
ge-1/0/2.107,up,up,inet|multiservice,"10.187.132.193/27,10.187.132.194/27"
ge-1/1/4,up,up
ge-1/1/5.0,up,up,inet|iso|mpls|multiservice,10.164.69.209/30
我试过使用grep interfacename-A4,但它无法显示其他界面信息

#!/bin/bash

show() {
    [ "$ge" ] || return
    [ "$add_quotes" ] && iprange="\"$iprange\""
    out="$ge,$upd1,$upd2,$service,$iprange"
    out="${out%%,}"
    echo "${out%%,}"
}

while read line
do 
    case "$line" in
        ge*)
            show
            read ge upd1 upd2 service iprange < <( echo "$line" )
            add_quotes=
            ;;
        [0-9]*)
            iprange="$iprange,$line"
            add_quotes=Y
            ;;
        *) 
            service="$service|$line"
            ;;
    esac
done

# Show last line
show
工作原理:此脚本逐行读取标准数据(
,同时读取行
)。然后将每一行分为三种类型:(a)新记录(即以“ge-”开头的行),(b)提供另一IP范围的连续记录(即以数字开头的记录),或(c)提供另一服务的连续记录(即以字母开头的记录)。依次处理这些案件:

(a) 当该行包含新记录的开始时,这意味着上一条记录已结束,因此我们使用
show
功能将其打印出来。然后我们从新行中读到我命名的五列:ge upd1 upd2服务iprange。然后,我们将add_quotes变量重置为空

(b) 当该行仅包含另一个IP范围时,我们将其添加到当前IP范围。根据问题中的示例,两个或多个IP范围的组合用逗号分隔,并用引号括起来。因此,我们将
add_quotes
设置为“Y”

(c) 当该行包含附加服务时,我们将其添加到服务变量中。根据问题中的示例,两个服务由竖条“|”分隔,不使用引号

函数
show
首先通过检查
ge
变量是否为非空来检查是否有要显示的记录。如果为空,则执行
return
语句,使函数退出(返回),而不处理其任何其他语句。如果
$ge
为非空,则函数将继续执行下一条语句,如果需要,该语句将在IP范围变量周围添加引号。然后,它将变量与分隔它们的逗号组合,删除尾随的逗号(如问题中的示例所示),并将结果发送给stdout

工作原理:此脚本逐行读取标准数据(
,同时读取行
)。然后将每一行分为三种类型:(a)新记录(即以“ge-”开头的行),(b)提供另一IP范围的连续记录(即以数字开头的记录),或(c)提供另一服务的连续记录(即以字母开头的记录)。依次处理这些案件:

(a) 当该行包含新记录的开始时,这意味着上一条记录已结束,因此我们使用
show
功能将其打印出来。然后我们从新行中读到我命名的五列:ge upd1 upd2服务iprange。然后,我们将add_quotes变量重置为空

(b) 当该行仅包含另一个IP范围时,我们将其添加到当前IP范围。根据问题中的示例,两个或多个IP范围的组合用逗号分隔,并用引号括起来。因此,我们将
add_quotes
设置为“Y”

(c) 当该行包含附加服务时,我们将其添加到服务变量中。根据问题中的示例,两个服务由竖条“|”分隔,不使用引号

函数
show
首先通过检查
ge
变量是否为非空来检查是否有要显示的记录。如果为空,则执行
return
语句,使函数退出(返回),而不处理其任何其他语句。如果
$ge
为非空,则函数将继续执行下一条语句,如果需要,该语句将在IP范围变量周围添加引号。然后,它将变量与分隔变量的逗号组合,删除尾随的逗号(如问题中的示例所示),并将结果发送到stdout。

parselog.awk
#/usr/bin/gawk-f
开始{
RS=“[^\n]*\n([^\n]*\n)*”
OFS=“,”
}
长度(RT)>0{
$0=RT#见:http://stackoverflow.com/a/11917783/27581
opts=“”
ips=“”
对于(i=4;i 0){
列表=列表分隔符
}
返回列表val
}
用法
$。/parselog.awk
parselog.awk
#/usr/bin/gawk-f
开始{
RS=“[^\n]*\n([^\n]*\n)*”
OFS=“,”
}
长度(RT)>0{
$0=RT#见:http://stackoverflow.com/a/11917783/27581
opts=“”
ips=“”
对于(i=4;i 0){
列表=列表分隔符
}
返回列表val
}
用法
$。/parselog.awk
大致上,我得到的是,这个脚本尝试逐行提取,当它遇到ge*接口时,它将处理,也将处理ip地址[0-9]。你能解释一下为什么我们使用add_quotes=Y吗?我添加了一个很长的解释。至于在IP范围周围添加引号的决定,它只是遵循问题中的示例输出:除了两个IP范围用逗号组合在一起时,IP范围周围没有引号。基本上,我得到的是,这个脚本尝试逐行提取,当它的meet ge*接口时,它将处理,也将处理IP地址[0-9]。你能解释一下为什么我们使用add_quotes=Y吗?我添加了一个很长的解释。至于在IP范围周围添加引号的决定,它只是按照问题中的示例输出:IP范围周围没有引号,除非两个IP范围用逗号组合在一起。
ge-1/0/0.0,up,down,inet|multiservice,10.100.100.1/24
ge-1/0/2.107,up,up,inet|multiservice,"10.187.132.193/27,10.187.132.194/27"
ge-1/1/4,up,up
ge-1/1/5.0,up,up,inet|iso|mpls|multiservice,10.164.69.209/30
#!/usr/bin/gawk -f

BEGIN {
    RS = "[^\n]*\n( [^\n]*\n)*"
    OFS = ","
}

length(RT) > 0 {
    $0 = RT     # See: http://stackoverflow.com/a/11917783/27581

    opts = ""
    ips = ""
    for (i = 4; i <= NF; ++i) {
        if (isIP($i)) {
            ips = append(ips, $i, ",")
        } else {
            opts = append(opts, $i, "|")
        }
    }
    print $1, $2, $3, opts, "\"" ips "\""
}

function isIP(str) {
    return str ~ /^[0-9]/
}

function append(list, val, separator) {
    if (length(list) > 0) {
        list = list separator
    }
    return list val
}
$ ./parselog.awk < log.txt 
ge-1/0/0.0,up,down,inet|multiservice,"10.100.100.1/24"
ge-1/0/2.107,up,up,inet|multiservice,"10.187.132.193/27,10.187.132.194/27"
ge-1/1/4,up,up,,""
ge-1/1/5.0,up,up,inet|iso|mpls|multiservice,"10.164.69.209/30"