J'ai 2 fichiers CSV:
Fichier d'objets:
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
Fichier de services:
DESCRIPTION,OrgIP,Service
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow
Le fichier d’objets a 3000 lignes, le fichier de service environ 500.
Je souhaite créer un nouveau fichier contenant toutes les lignes des services avec les champs des objets ajoutés là où une correspondance est trouvée dans la description. Donc, le résultat souhaité ressemblerait à ceci:
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
Utiliser 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
: traite la première ligne de chaque fichier comme des en-têtes de champ, en les imprimant sans essayer de les lier-t,
: définit ,
comme séparateur de champs d'entrée et de sortie-11
: rejoint le champ n ° 1 de services
-23
: rejoint le champ n ° 3 de objects
-a1
: imprime également les lignes imparables de services
<(awk 'NR > 1 {print | "sort -t, -k1"; next} 1' services)
: trie services
sur la colonne 1
en excluant l'en-tête<(awk 'NR > 1 {print | "sort -t, -k3"; next} 1' objects)
: trie objects
sur la colonne 3
en excluant l'en-tête% 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
Si vous avez installé sqlite3 et python sur votre système, vous pouvez utiliser ceci http://www.sqlet.com/ .
La commande SQL correspondante serait:
./sqlet.py -d',' -A file1.txt -B file2.txt 'select A3,B2,B3,A1,A2 from A LEFT JOIN B ON A3=B1;' | sqlite3
Cela nécessite que vous supprimiez les en-têtes des deux fichiers. Le script sqlet doit être extrait dans le même dossier où se trouvent ces deux fichiers ou modifié en conséquence.
Je l'ai essayé sur votre extrait d'exemple. Ça marche:
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
Si les fichiers ne sont pas trop volumineux, qu'en est-il de 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
Tu peux faire:
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)
<()
est la syntaxe de substitution de processus, bash
le remplacera par un descripteur de fichier contenant le résultat de la commande.
head -1 f1.txt; tail -n +2 f2.txt | sort -t, -k1,1
sera sort
le premier fichier sur le premier champ de la deuxième ligne au repos et la première ligne est ajoutée en haut afin que nous puissions l'utiliser avec join
. Il en va de même pour f2.txt
avec le champ à sort
selon trois.
join
va juste rejoindre le premier champ de f1.txt
et le troisième de f2.txt
comme champs communs.
Exemple:
$ 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