Как объединить два CSV-файла, но только там, где совпадают 2-ые файлы?

У меня есть 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
2
задан 7 April 2016 в 06:09

4 ответа

Используя 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
1
ответ дан 7 April 2016 в 16:09

Если файлы не слишком огромны, как насчет 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
1
ответ дан 7 April 2016 в 16:09
  • 1
    Можно скорректировать скорость курсора также, но я уезжаю теперь. Между тем можно спросить " как скорректировать скорость курсора в libinput" как новый вопрос. Если никто не ответит, я посмотрю на него сегодня вечером. – Pilot6 15 August 2017 в 22:25

Если у Вас есть 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
ответ дан 7 April 2016 в 16:09
  • 1
    О, тот раздел сенсорной панели, я смотрел на " Inputclass" взгляды там были чем-то не так. Это работает теперь, спасибо. НО скорость курсора является все еще медленной. – MichaelX 15 August 2017 в 22:22

Можно сделать:

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
1
ответ дан 7 April 2016 в 16:09

Другие вопросы по тегам:

Похожие вопросы: