J'utilise la commande standard de jointure pour joindre deux fichiers triés en fonction de column1. La commande est une simple jointure fichier1 fichier2> fichier_sortie.
Mais comment puis-je joindre 3 fichiers ou plus en utilisant la même technique? Rejoindre fichier1 fichier2 fichier3> fichier_sortie La commande ci-dessus m'a donné un fichier vide. Je pense que sed peut m'aider, mais Je ne sais pas trop comment?
man join
:
NAME
join - join lines of two files on a common field
SYNOPSIS
join [OPTION]... FILE1 FILE2
cela ne fonctionne qu'avec deux fichiers.
si vous devez en rejoindre trois, vous pouvez peut-être d'abord rejoindre les deux premiers, puis rejoindre le troisième.
essayer:
join file1 file2 | join - file3 > output
qui devrait joindre les trois fichiers sans créer de fichier temporaire. -
indique à la commande join de lire le premier flux d'entrée de stdin
On peut joindre plusieurs fichiers (N> = 2) en construisant un pipeline de join
s de manière récursive:
#!/bin/sh
# multijoin - join multiple files
join_rec() {
if [ $# -eq 1 ]; then
join - "$1"
else
f=$1; shift
join - "$f" | join_rec "$@"
fi
}
if [ $# -le 2 ]; then
join "$@"
else
f1=$1; f2=$2; shift 2
join "$f1" "$f2" | join_rec "$@"
fi
Je sais que c’est une vieille question, mais pour référence future. Si vous savez que les fichiers que vous souhaitez rejoindre ont un motif semblable à celui de la question ici, par exemple. file1 file2 file3 ... fileN
Ensuite, vous pouvez simplement les rejoindre avec cette commande
cat file* > output
Où sortie sera la série des fichiers joints qui ont été joints dans l'ordre alphabétique.
J'ai créé une fonction pour cela. Le premier argument est le fichier de sortie, les arguments restants sont les fichiers à joindre.
function multijoin() {
out=$1
shift 1
cat $1 | awk '{print $1}' > $out
for f in $*; do join $out $f > tmp; mv tmp $out; done
}
Usage:
multijoin output_file file*
La page man
de join
indique qu'elle ne fonctionne que pour deux fichiers. Vous devez donc créer un fichier intermédiaire que vous supprimerez par la suite, à savoir:
> join file1 file2 > temp
> join temp file3 > output
> rm output
Un peu une vieille question, voici comment vous pouvez le faire avec une seule awk
:
awk -v j=<field_number> '{key=$j; $j=""} # get key and delete field j
(NR==FNR){order[FNR]=key;} # store the key-order
{entry[key]=entry[key] OFS $0 } # update key-entry
END { for(i=1;i<=FNR;++i) {
key=order[i]; print key entry[key] # print
}
}' file1 ... filen
Ce script suppose:
<field_number>
<field_number>
est un entier valide.Joindre joint des lignes de deux fichiers sur un champ commun. Si vous voulez en rejoindre plus, faites-le par paires. Joignez d’abord les deux premiers fichiers, puis joignez le résultat à un troisième fichier, etc.
En supposant que vous ayez quatre fichiers A.txt, B.txt, C.txt et D.txt en tant que:
~$ cat A.txt
x1 2
x2 3
x4 5
x5 8
~$ cat B.txt
x1 5
x2 7
x3 4
x4 6
~$ cat C.txt
x2 1
x3 1
x4 1
x5 1
~$ cat D.txt
x1 1
Joindre les fichiers avec:
firstOutput='0,1.2'; secondOutput='2.2'; myoutput="$firstOutput,$secondOutput"; outputCount=3; join -a 1 -a 2 -e 0 -o "$myoutput" A.txt B.txt > tmp.tmp; for f in C.txt D.txt; do firstOutput="$firstOutput,1.$outputCount"; myoutput="$firstOutput,$secondOutput"; join -a 1 -a 2 -e 0 -o "$myoutput" tmp.tmp $f > tempf; mv tempf tmp.tmp; outputCount=$(($outputCount+1)); done; mv tmp.tmp files_join.txt
Résultats:
~$ cat files_join.txt
x1 2 5 0 1
x2 3 7 1 0
x3 0 4 1 0
x4 5 6 1 0
x5 8 0 1 0