У меня есть 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
Используя 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
: соединения на поле № 1 services
-23
: соединения на поле № 3 objects
-a1
: также печатает unpairable строки от 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
Если файлы не слишком огромны, как насчет 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
Если у Вас есть 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
Можно сделать:
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