Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Bash或Awk脚本合并X个字段匹配的行,同时在不';不匹配_Linux_Bash_Awk_Scripting - Fatal编程技术网

Linux Bash或Awk脚本合并X个字段匹配的行,同时在不';不匹配

Linux Bash或Awk脚本合并X个字段匹配的行,同时在不';不匹配,linux,bash,awk,scripting,Linux,Bash,Awk,Scripting,需要:我有一个包含以下示例数据的文件。我需要: 当X个字段数匹配时,将所有行合并为一行 当值发生变化时,在X个字段中创建值范围 在这种情况下: 将所有行合并到一个字段$1到$6和$8匹配的行中,在字段中创建一系列相关值$7 或 将所有行合并到一个匹配的字段$1到$7中,在字段$8*中创建一个关联值范围 解决方案必须是Linux本机的(如bash或awk脚本),不需要安装其他软件(如datamash) @下面使用TCL的rtx13解决方案确实有效(再次感谢),我只是不确定是否可以在我的实时环境中安

需要:我有一个包含以下示例数据的文件。我需要:

  • 当X个字段数匹配时,将所有行合并为一行
  • 当值发生变化时,在X个字段中创建值范围
  • 在这种情况下: 将所有行合并到一个字段$1到$6和$8匹配的行中,在字段中创建一系列相关值$7

    将所有行合并到一个匹配的字段$1到$7中,在字段$8*中创建一个关联值范围

  • 解决方案必须是Linux本机的(如bash或awk脚本),不需要安装其他软件(如datamash)
  • @下面使用TCL的rtx13解决方案确实有效(再次感谢),我只是不确定是否可以在我的实时环境中安装TCL,所以我希望还可以提出AWK/BASH/等解决方案

    原始数据:

    HOST    FILTER  INTERFACE   SOURCE  DESTINATION PROTOCOL    SOURCE PORT DESTINATION PORT
    host1   input   nic1        ip1     ip2         PROT        30000       10
    host1   input   nic1        ip1     ip2         PROT        50000       10
    host1   input   nic1        ip1     ip2         PROT        60000       10
    host1   input   nic1        ip3     ip2         PROT        10          30000
    host1   input   nic1        ip3     ip2         PROT        10          50000
    host1   input   nic1        ip3     ip2         PROT        10          60000
    host1   output  nic1        ip2     ip1         PROT        10          30000
    host1   output  nic1        ip2     ip1         PROT        10          50000
    host1   output  nic1        ip2     ip1         PROT        10          60000
    host1   output  nic1        ip2     ip3         PROT        30000       10
    host1   output  nic1        ip2     ip3         PROT        60000       10
    host1   output  loc         ip2     ip2         PROT        10          30000
    host1   output  loc         ip2     ip2         PROT        10          50000
    
    host1   input   nic1        ip1     ip2         PROT        30000:60000 10
    host1   input   nic1        ip3     ip2         PROT        10          30000:60000
    host1   output  nic1        ip2     ip1         PROT        10          30000:60000
    host1   output  nic1        ip2     ip3         PROT        30000:60000 10
    host1   output  loc         ip2     ip2         PROT        10          30000:50000
    
    所需的处理输出:

    HOST    FILTER  INTERFACE   SOURCE  DESTINATION PROTOCOL    SOURCE PORT DESTINATION PORT
    host1   input   nic1        ip1     ip2         PROT        30000       10
    host1   input   nic1        ip1     ip2         PROT        50000       10
    host1   input   nic1        ip1     ip2         PROT        60000       10
    host1   input   nic1        ip3     ip2         PROT        10          30000
    host1   input   nic1        ip3     ip2         PROT        10          50000
    host1   input   nic1        ip3     ip2         PROT        10          60000
    host1   output  nic1        ip2     ip1         PROT        10          30000
    host1   output  nic1        ip2     ip1         PROT        10          50000
    host1   output  nic1        ip2     ip1         PROT        10          60000
    host1   output  nic1        ip2     ip3         PROT        30000       10
    host1   output  nic1        ip2     ip3         PROT        60000       10
    host1   output  loc         ip2     ip2         PROT        10          30000
    host1   output  loc         ip2     ip2         PROT        10          50000
    
    host1   input   nic1        ip1     ip2         PROT        30000:60000 10
    host1   input   nic1        ip3     ip2         PROT        10          30000:60000
    host1   output  nic1        ip2     ip1         PROT        10          30000:60000
    host1   output  nic1        ip2     ip3         PROT        30000:60000 10
    host1   output  loc         ip2     ip2         PROT        10          30000:50000
    
    我是否需要一个单独的文件列出我要合并的端口?因为这些也可能在一个范围内?所以脚本可以引用它来知道它是否是合并端口

    10|EXAMPLE
    22|SSH
    80|HTTP
    2049|NFS
    *etc*
    
    我正试图尽可能的具体,因为我原来的帖子被认为需要更多的关注;它收到了一个非常接近的答案(谢谢@Enrico Maria De Angelis),但并非完全如此,还有一个使用datamash的答案(谢谢@oguz ismail),效果很好,但遗憾的是,我需要一个不需要安装附加软件的解决方案:

    以下内容一次只能在一列上工作


    mergecolumn
    脚本:

    #!/usr/bin/tclsh
    # check for column number
    if { ![llength $argv] || ![regexp {^\d+$} [lindex $argv 0] merge_column] } {
        puts stderr "usage: $argv0 column (0-based)"
        exit 1
    }
    
    # read data in and store into 'output' array and 'row_key' list
    set rows [lrange [split [read -nonewline stdin] "\n"] 1 end]
    foreach row $rows {
        set value [lindex $row $merge_column]
        set row [lreplace $row $merge_column $merge_column "%s"]
        if { ![info exist output($row)] } {
            lappend row_key $row
        }
        lappend output($row) $value
    }
    
    # iterate over 'row_key' and generate output
    foreach row $row_key {
        if { [llength $output($row)] > 1 } {
            set o [lreplace [lsort -dictionary $output($row)] 1 end-1]
        } else {
            set o $output($row)
        }
        puts [format $row [join $o :]]
    }
    
    #!/usr/bin/tclsh
    
    # read data in and store into 'output' array and 'row_key' list
    set rows [lrange [split [read -nonewline stdin] "\n"] 1 end]
    foreach row $rows {
        if { [lsearch -exact $argv [lindex $row 6]] >= 0 } {
            set merge_column 7
        } elseif { [lsearch -exact $argv [lindex $row 7]] >= 0 } {
            set merge_column 6
        } else {
            set merge_column -1 ;# do not merge
        }
        if { $merge_column >= 0 } {
            set value [lindex $row $merge_column]
            set row [lreplace $row $merge_column $merge_column "%s"]
        } else {
            set value ""
            set row [list {*}$row] ;# trim spaces for consistency
        }
        if { ![info exist output($row)] } {
            lappend row_key $row
        }
        lappend output($row) $value
    }
    
    # iterate over 'row_key' and generate output
    foreach row $row_key {
        if { [llength $output($row)] > 1 } {
            set o [lreplace [lsort -dictionary $output($row)] 1 end-1]
        } else {
            set o $output($row)
        }
        puts [format $row [join $o :]]
    }
    

    终端会话:

    $cat数据
    主机筛选器接口源目标协议源端口目标端口
    主机1输入nic1 ip1 ip2保护30000 10
    主机1输入nic1 ip1 ip2保护50000 10
    主机1输入nic1 ip1 ip2保护60000 10
    主机1输入nic1 ip3 ip2保护10 30000
    主机1输入nic1 ip3 ip2保护10 50000
    主机1输入nic1 ip3 ip2保护10 60000
    主机1输出nic1 ip2 ip1保护10 30000
    主机1输出nic1 ip2 ip1保护10 50000
    主机1输出nic1 ip2 ip1保护10 60000
    主机1输出nic1 ip2 ip3保护30000 10
    主机1输出nic1 ip2 ip3保护60000 10
    主机1输出位置ip2 ip2保护10 30000
    主机1输出位置ip2 ip2保护10 50000
    美元/合并第6列<数据
    主机1输入nic1 ip1 ip2保护30000:60000 10
    主机1输入nic1 ip3 ip2保护10 30000
    主机1输入nic1 ip3 ip2保护10 50000
    主机1输入nic1 ip3 ip2保护10 60000
    主机1输出nic1 ip2 ip1保护10 30000
    主机1输出nic1 ip2 ip1保护10 50000
    主机1输出nic1 ip2 ip1保护10 60000
    主机1输出nic1 ip2 ip3保护30000:60000 10
    主机1输出位置ip2 ip2保护10 30000
    主机1输出位置ip2 ip2保护10 50000
    美元/合并第7列<数据
    主机1输入nic1 ip1 ip2保护30000 10
    主机1输入nic1 ip1 ip2保护50000 10
    主机1输入nic1 ip1 ip2保护60000 10
    主机1输入nic1 ip3 ip2保护10 30000:60000
    主机1输出nic1 ip2 ip1保护10 30000:60000
    主机1输出nic1 ip2 ip3保护30000 10
    主机1输出nic1 ip2 ip3保护60000 10
    主机1输出位置ip2 ip2保护10 30000:50000
    $ 
    
    以下内容适用于两列。通过命令行提供要合并的端口列表


    mergecolumn2
    脚本:

    #!/usr/bin/tclsh
    # check for column number
    if { ![llength $argv] || ![regexp {^\d+$} [lindex $argv 0] merge_column] } {
        puts stderr "usage: $argv0 column (0-based)"
        exit 1
    }
    
    # read data in and store into 'output' array and 'row_key' list
    set rows [lrange [split [read -nonewline stdin] "\n"] 1 end]
    foreach row $rows {
        set value [lindex $row $merge_column]
        set row [lreplace $row $merge_column $merge_column "%s"]
        if { ![info exist output($row)] } {
            lappend row_key $row
        }
        lappend output($row) $value
    }
    
    # iterate over 'row_key' and generate output
    foreach row $row_key {
        if { [llength $output($row)] > 1 } {
            set o [lreplace [lsort -dictionary $output($row)] 1 end-1]
        } else {
            set o $output($row)
        }
        puts [format $row [join $o :]]
    }
    
    #!/usr/bin/tclsh
    
    # read data in and store into 'output' array and 'row_key' list
    set rows [lrange [split [read -nonewline stdin] "\n"] 1 end]
    foreach row $rows {
        if { [lsearch -exact $argv [lindex $row 6]] >= 0 } {
            set merge_column 7
        } elseif { [lsearch -exact $argv [lindex $row 7]] >= 0 } {
            set merge_column 6
        } else {
            set merge_column -1 ;# do not merge
        }
        if { $merge_column >= 0 } {
            set value [lindex $row $merge_column]
            set row [lreplace $row $merge_column $merge_column "%s"]
        } else {
            set value ""
            set row [list {*}$row] ;# trim spaces for consistency
        }
        if { ![info exist output($row)] } {
            lappend row_key $row
        }
        lappend output($row) $value
    }
    
    # iterate over 'row_key' and generate output
    foreach row $row_key {
        if { [llength $output($row)] > 1 } {
            set o [lreplace [lsort -dictionary $output($row)] 1 end-1]
        } else {
            set o $output($row)
        }
        puts [format $row [join $o :]]
    }
    

    终端会话:

    $。/mergecolumn2
    您能否澄清合并要求?看起来您还需要将所有行合并为一个字段$1到$6和$7匹配的行,在字段$8中创建一个关联值范围…@rtx13 Argh,抱歉,这是我第一次尝试发布内容!没错,有两种情况需要合并。我已经用第二种方案更新了我的帖子。@rtx13您的评论也让我认为我需要一个单独的文件,其中列出了我要合并的特定端口?没问题,只是想了解问题的范围。您是否碰巧在需要运行此代码的系统上提供了
    tcl
    ?您可以从shell/终端运行
    tclsh
    进行检查。@rtx13它当前没有安装tcl,但是它看起来像是直接从Redhat获得的,所以我可以从本地repo中提取它。OP对tcl没有问题。请参阅问题下方的评论和聊天。非常感谢tcl脚本。我仍然不确定是否可以在我的环境中安装tcl,但在测试系统上使用它非常有吸引力。干得好@juggy_gales很乐意帮忙。如果此答案或任何其他答案解决了您的问题,请将其标记为已接受。要接受答案,请单击复选标记按钮(✓) 恩德内亚