我有 2 个 CSV 文件:
对象文件:
IP,MASK,DESCRIPTION
10.10.3.94,255.255.255.255,Rob
10.10.3.95,255.255.255.255,Mark
10.10.3.96,255.255.255.255,John
服务文件:
DESCRIPTION,OrgIP,Service
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow
对象文件有 3000 行,服务文件有大约 500 行。
我想创建一个新文件,其中包含服务中的所有行,并在描述中找到匹配项的位置添加对象字段。因此所需的输出将如下所示:
DESCRIPTION,OrgIP,Service,IP,MASK
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
答案1
如果你的系统上安装了 sqlite3 和 python,你可以使用这个http://www.sqlet.com/。
相关的 SQL 命令是:
./sqlet.py -d',' -A file1.txt -B file2.txt 'select A3,B2,B3,A1,A2 from A LEFT JOIN B ON A3=B1;' | sqlite3
这要求您从这两个文件中删除标题。sqlet 脚本必须提取到这两个文件所在的同一文件夹中,或进行相应修改。
我在你的示例摘录上尝试了它。它有效:
bruni@bruni-Inspiron-5547:~/Downloads$ cat file1.txt
10.10.3.94,255.255.255.255,Rob
10.10.3.95,255.255.255.255,Mark
10.10.3.96,255.255.255.255,John
bruni@bruni-Inspiron-5547:~/Downloads$ cat file2.txt
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow
bruni@bruni-Inspiron-5547:~/Downloads$ ./sqlet.py -d',' -A file1.txt -B file2.txt 'select A3,B2,B3,A1,A2 from A LEFT JOIN B ON A3=B1;' | sqlite3
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
答案2
使用join
:
join --header -t, -11 -23 -a1 <(awk 'NR > 1 {print | "sort -t, -k1"; next} 1' services) <(awk 'NR > 1 {print | "sort -t, -k3"; next} 1' objects)
join --header -t, -11 -23 -a1 <(
awk '
NR > 1 {
print |
"sort -t, -k1";
next
}
1
' services
) <(
awk '
NR > 1 {
print |
"sort -t, -k3";
next
}
1
' objects
)
--header
:将每个文件的第一行视为字段标题,打印它们而不尝试将它们配对-t,
:设置,
为输入和输出字段分隔符-11
:连接到字段 #1services
-23
:连接到字段 #3objects
-a1
: 还打印不成对的行services
<(awk 'NR > 1 {print | "sort -t, -k1"; next} 1' services)
:services
按1
除标题之外的列排序<(awk 'NR > 1 {print | "sort -t, -k3"; next} 1' objects)
:objects
按3
除标题之外的列排序
% cat objects
IP,MASK,DESCRIPTION
10.10.3.94,255.255.255.255,Rob
10.10.3.95,255.255.255.255,Mark
10.10.3.96,255.255.255.255,John
% cat services
DESCRIPTION,OrgIP,Service
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow
% join --header -t, -11 -23 -a1 <(awk 'NR > 1 {print | "sort -t, -k1"; next} 1' services) <(awk 'NR > 1 {print | "sort -t, -k3"; next} 1' objects)
DESCRIPTION,OrgIP,Service,IP,MASK
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255
答案3
如果文件不是太大,怎么样awk
?
$ awk -F, 'NR==FNR {a[$1]=$2 FS $3 FS $4; next} $3 in a {OFS=","; print $3,a[$3],$2}' services objects
DESCRIPTION,OrgIP,Service,IP,MASK
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
答案4
你可以做:
join -t, -a2 -11 -23 <(head -1 f1.txt; tail -n +2 f1.txt | \
sort -t, -k1,1) <(head -1 f2.txt; tail -n +2 f2.txt | sort -t, -k3,3)
<()
是进程替换语法,bash
将用文件描述符替换它,其中包含命令的输出作为内容head -1 f1.txt; tail -n +2 f2.txt | sort -t, -k1,1
将sort
第一个文件的第一个字段从第二行添加到其余行,并将第一行添加到顶部,以便我们可以使用它join
。 同样适用于根据f2.txt
字段为三。sort
join
将仅将的第一个字段f1.txt
和第三个字段f2.txt
作为公共字段加入。
例子:
$ cat f1.txt
DESCRIPTION,OrgIP,Service
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow
$ cat f2.txt
IP,MASK,DESCRIPTION
10.10.3.94,255.255.255.255,Rob
10.10.3.95,255.255.255.255,Mark
10.10.3.96,255.255.255.255,John
$ join -t, -11 -23 <(head -1 f1.txt; tail -n +2 f1.txt | sort -t, -k1,1) <(head -1 f2.txt; tail -n +2 f2.txt | sort -t, -k3,3)
DESCRIPTION,OrgIP,Service,IP,MASK
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255