我需要比较两个输入文件(file1.csv和file2.csv(并存储结果和第三个文件(file3.csv(。
条件如下:
- 如果条目与file1和file2匹配,则将其存储在file3中
- 如果在文件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类似的想法,但:
- 使用提供的文件名
- 脚本中的硬代码文件名而不是参数,因为它们不可互换
- 请求订单中的产量结果
您可以将脚本保存为task
、chmod 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
}
}