比较两个文件并根据条件输出结果



我需要比较两个输入文件(file1.csv和file2.csv(并存储结果和第三个文件(file3.csv(。

条件如下:

  1. 如果条目与file1和file2匹配,则将其存储在file3中
  2. 如果在文件1中找到条目,请将其存储在文件3中

看起来像这样:

输入:file1.csv

"switch10"
"switch33"
"router51"
"switch6"
"router44"
"router12"
"switch2"

输入:file2.csv

"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"
"router44";"DatacenterC - cab2";"Test - Tenant2"

结果:file3.csv

"router12"
"router44";"DatacenterC - cab2";"Test - Tenant2"
"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"
"switch6"
"switch10"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"

我试过很多使用"awk"的组合;但是我不能构造条件句。

我想知道是否有人可以帮助我构建条件来构建这个结果文件3.csv.

我们非常感谢您的协助。

在每个Unix框的任何shell中使用任何awk,并假设您引用的字段不包含;s,并且您不关心输出顺序:

$ cat tst.awk
BEGIN { FS=";" }
NR==FNR {
first[$1]
next
}
{
print
delete first[$1]
}
END {
for ( i in first ) {
print i
}
}

$ awk -f tst.awk file1.csv file2.csv
"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"
"router44";"DatacenterC - cab2";"Test - Tenant2"
"switch6"
"router12"
"switch10"

如果你确实关心输出顺序,你可以将装饰/排序/取消装饰习惯用法与任何awk+排序+剪切一起使用:

$ cat tst.awk
BEGIN { FS=OFS=";" }
NR==FNR {
first[$1]
next
}
{
prt($0)
delete first[$1]
}
END {
for ( i in first ) {
prt(i)
}
}
function prt(str,       arr, alpha, numeric) {
split(str,arr)
alpha = numeric = arr[1]
sub(/[0-9].*/,"",alpha)
gsub(/[^0-9]/,"",numeric)
print alpha, numeric, str
}

$ awk -f tst.awk file1.csv file2.csv | sort -t';' -k1,1 -k2,2n | cut -d';' -f3-
"router12"
"router44";"DatacenterC - cab2";"Test - Tenant2"
"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"
"switch6"
"switch10"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"

我将使用GNUAWK执行以下任务,让file1.txt内容为

"switch10"
"switch33"
"router51"
"switch6"
"router44"
"router12"
"switch2"

CCD_ 4内容为

"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"
"router44";"DatacenterC - cab2";"Test - Tenant2"

然后

awk 'BEGIN{FS=";"}(NR==FNR){arr[$1]=$0}((NR!=FNR)&&($1 in arr)){arr[$1]=$0}END{for(i in arr){print arr[i]}}' file1.txt file2.txt

输出

"switch6"
"router12"
"router44";"DatacenterC - cab2";"Test - Tenant2"
"router51";"DatacenterA - cab1";"Prod - Tenant12"
"switch33";"DatacenterB - cab14";"Prod - Tenant4"
"switch10"
"switch2";"DatacenterA - cab3";"Dev - Tenant5"

免责声明:我认为您可以接受输出文件中的任何行顺序。说明:我通知GNUAWK;被用作字段分隔符(FS(,然后在处理第一个文件(NR==FNR(时,我通过将整个当前行($0(放在作为第一个字段($1(内容的密钥下来填充数组arr。在处理下一个文件(NR!=FNR(时,如果有对应于数组arr中行的第一个字段的值,则我将其值更新为整个当前行。在处理完所有文件后,我使用for对数组arr中的所有值执行print

(在gawk 4.2.1中测试(

如果awk不是强制性的,您可以使用伟大而简单的Miller

运行

mlr --csv --fs ";" -N join --ul -j 1 -f input_01.csv then unsparsify then sort -f 1 input_02.csv

你有

router12;;
router44;DatacenterC - cab2;Test - Tenant2
router51;DatacenterA - cab1;Prod - Tenant12
switch10;;
switch2;DatacenterA - cab3;Dev - Tenant5
switch33;DatacenterB - cab14;Prod - Tenant4
switch6;;

一些注意事项:

  • --csv --fs ";"设置输入和输出为CSV,其中字段分隔符为;
  • CCD_ 19设置输入和输出不具有标题行
  • join --ul -j 1基于第一列运行左联接

与@Daweo类似的想法,但:

  1. 使用提供的文件名
  2. 脚本中的硬代码文件名而不是参数,因为它们不可互换
  3. 请求订单中的产量结果

您可以将脚本保存为taskchmod 755 task,然后将其运行为./task > file3.csv:

#!/usr/bin/env -S awk -F; -f
BEGIN {
while ( (getline <"file2.csv") > 0 ) {
lookup[$1] = $0
}
while ( ("sort -k1.1,1.7 -k1.8n file1.csv" | getline) > 0 ) {
print ($0 in lookup) ? lookup[$0] : $0
}
}

注意:这里使用的排序是脆弱的,因为它依赖于固定大小的前缀(路由器或交换机(来识别复合密钥的两个部分。

使用gawk的PROCINFO["sorted_in"]功能以指定顺序返回密钥,并使用自定义比较函数str_num_cmp()使其更加健壮:

#!/usr/bin/env -S awk -F; -f
function str_num_to_a(i, a) {
match(i, /"([^0-9]*)([0-9]+)"/, a)
}
# a1/a2 are specified as arguments to make them local variables
function str_num_cmp(i1, v1, i2, v2, a1, a2) {
str_num_to_a(i1, a1)
str_num_to_a(i2, a2)
if(a1[1] < a2[1])
return -1
if(a1[1] == a2[1]) {
if(a1[2] < a2[2])
return -1
if(a1[2] == a2[2])
return 0
}
return 1
}
BEGIN {
while ( (getline <"file1.csv") > 0 ) {
keys[$1] = ""
}
while ( (getline <"file2.csv") > 0 ) {
lookup[$1] = $0
}
PROCINFO["sorted_in"] = "str_num_cmp"
for (k in keys) {
print (k in lookup) ? lookup[k] : k
}
}

相关内容

  • 没有找到相关文章

最新更新