linux - Bash 或 Awk 脚本用于合并 X 个字段匹配的行,同时在不匹配的字段中创建范围
问题描述
需要:我有一个包含如下示例数据的文件。我需要:
- 当 X 个字段匹配时,将所有行合并为一行
- 当值变化时,在 X 个字段中创建值范围
在这种情况下:将所有行合并到一个字段 $1 到 $6 和 $8 匹配的行中,在字段$7中创建一系列关联值
或者
将所有行合并为一个字段 $1 到 $7匹配的行,在字段$8*中创建一系列关联值
- 解决方案必须是 Linux 原生的(如 bash 或 awk 脚本),不需要安装额外的软件(例如 datamash)。
@rtx13 下面使用 TCL 的解决方案确实有效(再次感谢),我只是不确定我是否可以在我的实时环境中安装 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
我是否需要一个单独的文件来列出我想要合并的端口?因为这些也可能在一个范围内?所以脚本可以引用它来知道它是否是一个合并端口?
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 :]]
}
终端会话:
$ 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
$
推荐阅读
- python - 函数如何像描述符一样工作?
- java - 使用 Mongo 存储库按属性分组
- linux - linux中的mailx命令限制
- python - Python NLP 预测匹配词
- c# - 如何从自定义渲染器设置 Xamarin.Forms 元素 BindableProperties?
- javascript - 用正则表达式匹配 Javascript 中的 cookie 字符串
- windows - PowerShell 脚本无法识别我正在使用的路径
- excel - 将单元格值从一张表复制并粘贴到另一张表
- node.js - 未找到 AWS Elastic Beanstalk Docker 节点 Typescript 入口点
- python-3.x - python f-string在制作文件列表时包括除0之外的所有数字