bash文本处理以删除ASCII并从结果中获得唯一行



在linux中,下面的命令

terraform providers

输出结果如下

.
├── provider[xxx.com/edu/xxxvenafi] 1.2.0
├── provider[registry.terraform.io/hashicorp/kubernetes] 2.3.2
├── provider[xxx.com/edu/xxxsmaas] 1.0.1
├── provider[registry.terraform.io/hashicorp/aws]
├── module.standard_deployment
│   ├── provider[xxx.com/edu/xxxsmaas] 1.0.1
│   ├── provider[xxx.com/edu/xxxvenafi] 1.2.0
│   ├── provider[registry.terraform.io/hashicorp/kubernetes]
│   └── provider[registry.terraform.io/hashicorp/local]
└── module.standand_ingress
├── provider[registry.terraform.io/hashicorp/kubernetes]
├── provider[xxx.com/edu/xxxsmaas] 1.0.1
├── provider[xxx.com/edu/xxxvenafi] 1.2.0
└── provider[registry.terraform.io/hashicorp/aws]
Providers required by state:
provider[xxx.com/edu/xxxsmaas]
provider[xxx.com/edu/xxxvenafi]
provider[registry.terraform.io/hashicorp/aws]
provider[registry.terraform.io/hashicorp/kubernetes]

从输出中删除这些树结构的最佳方法是什么?最终目标是只列出唯一的行,如下所示

provider[xxx.com/edu/xxxvenafi] 1.2.0    
provider[xxx.com/edu/xxxsmaas] 1.0.1
$ awk '/[0-9]$/ && sub(/[^[:alpha:]]+/,"") && !seen[$0]++' file
provider[xxx.com/edu/xxxvenafi] 1.2.0
provider[registry.terraform.io/hashicorp/kubernetes] 2.3.2
provider[xxx.com/edu/xxxsmaas] 1.0.1

或者如果你真的只希望行以1.0.1或1.2.0结尾,就像你在评论中说的:

$ awk '/ 1.((0.1)|(2.0))$/ && sub(/[^[:alpha:]]+/,"") && !seen[$0]++' file
provider[xxx.com/edu/xxxvenafi] 1.2.0
provider[xxx.com/edu/xxxsmaas] 1.0.1

使用sedsort,您可以尝试以下操作

$ sed -E 's/.*(provider.*)/1/g;/^[a-z]/!d' input_file | sort -u
provider[registry.terraform.io/hashicorp/aws]
provider[registry.terraform.io/hashicorp/kubernetes]
provider[registry.terraform.io/hashicorp/kubernetes] 2.3.2
provider[registry.terraform.io/hashicorp/local]
provider[xxx.com/edu/xxxsmaas] 1.0.1
provider[xxx.com/edu/xxxvenafi] 1.2.0

这可能不是最有效的。

编辑

摘自Hai Vu的评论,这里有一个适用于op的grep替代方案。

terraform providers | grep -o 'provider.*[0-9][^]]*$' | sort -u

With awk:

terrraform providers |
awk 'BEGIN {FS="provider"}
/xxx.com/ && NF==2 {printf("%s%sn", FS, $2)}' | 
sort -u

或避免调用sort:

terrraform providers |
awk 'BEGIN {FS="provider"}
/xxx.com/ && NF==2 {a[$2]}
END {
for (key in a) {
printf("provider%sn", key)
}
}'

这可能适合您(GNU sed):

sed -nE 's/.*(provider)/1/;ta;$!d;bb;:a;H;g
s/((nS+]).*)2[^n]*$/1/;h;$!d;:b;x;s/.//p' file

关闭隐式打印-n,打开扩展regexp-E

匹配包含provider的行,删除任何序言并跳转到:a

如果没有找到匹配,并且不是最后一行,则删除它并重复。

如果没有找到匹配并且是最后一行,则跳转到:b

:a处,将当前行附加到保持空间,然后将保持空间复制到当前行。

使用模式匹配,将以前的线路键与当前线路键进行比较,如果已经添加了该键,则删除当前线路。

将结果复制到保持空间,如果不是最后一行,则删除并重复。

在文件末尾:b,交换到保持空间,删除开始处引入的换行符并打印结果。

最新更新