Bash или скрипт Awk для слияния строк, в которых совпадает число полей X при создании диапазонов в полях, которые не совпадают - PullRequest
2 голосов
/ 31 марта 2020

NEED : у меня есть файл, содержащий данные, как в примере ниже. Мне нужно:

  1. Объединить все строки в одну строку, когда число полей X соответствует
  2. Создать диапазон значений в количестве X полей, когда значения варьируются

В этом случае: объедините все строки в одну, где поля от $ 1 до $ 6 и $ 8 соответствуют , создайте диапазон связанных значений в поле $ 7

ИЛИ

Объединить все строки в одну, где совпадают поля от $ 1 до $ 7 , создать диапазон связанных значений в поле $ 8 *

Решение должно быть чем-то родным для Linux (например, bash или сценарий awk), которое не требует установки дополнительного программного обеспечения (например, datama sh).

Приведенное ниже решение @ rtx13 с использованием TCL работает (спасибо еще раз), я просто не уверен, смогу ли я установить TCL в моей среде, поэтому надеюсь и AWK / BASH / et c. Также может быть предложено решение.

Исходные данные:

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*

Я пытаюсь быть настолько точным, насколько это возможно c, поскольку мой первоначальный пост, как считалось, требует большего внимания ; он получил ответ (Спасибо, @Enrico Maria De Angelis), который был близок, но не совсем так же, как и тот, который использовал datama sh (Спасибо @oguz ismail), который работал великолепно, но, к сожалению, мне нужен Решение, не требующее установки дополнительного программного обеспечения: Объедините все строки, которые идентичны, кроме ключевого поля и сделайте ключевое поле диапазоном

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Следующие работы на обеих колонках. Укажите список портов для объединения через командную строку.


mergecolumn2 script:

#!/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 < data
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
$ ./mergecolumn2 10 22 80 2049 < data
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
$ 
1 голос
/ 31 марта 2020

Следующие операции работают с одним столбцом одновременно.


mergecolumn script:

#!/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 :]]
}

Сеанс терминала:

$ cat data
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
$ ./mergecolumn 6 < data
host1 input nic1 ip1 ip2 PROT 30000: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:60000 10
host1 output loc ip2 ip2 PROT 10 30000
host1 output loc ip2 ip2 PROT 10 50000
$ ./mergecolumn 7 < data
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:60000
host1 output nic1 ip2 ip1 PROT 10 30000: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:50000
$ 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...