J'ai un fichier nom.txt d'une colonne, par exemple.
A
B
C
D
E
F
Ensuite, j'ai de nombreux fichiers, par ex. x.txt, y.txt et z.txt
x.txt a
A 1
C 3
D 2
y.txt a
A 1
B 4
E 3
z.txt a
B 2
D 2
F 1
La sortie souhaitable est (remplissage de 0 s'il n'y a pas de cartographie)
A 1 1 0
B 0 4 2
C 3 0 0
D 2 0 2
E 0 3 0
F 0 0 1
Est-il possible de le faire avec Bash? (peut-être awk?)
Merci beaucoup!!!
premières modifications - Mes efforts provisoires
[.____] Comme je suis assez nouveau à bash, il est vraiment difficile de comprendre une solution possible avec Awk. Je connais plus avec R, dans lequel cela peut être accompli par
namematrix[namematrix[,1]==xmatrix[,1],]
Dans l'ensemble, j'apprécie vraiment le type d'aide ci-dessous me aider à en apprendre davantage sur awk
et join
!
Édite secondaire - Une approche super efficace figurait!
Heureusement, inspiré par certaines réponses vraiment brillantes ci-dessous, j'ai réglé une manière très efficace de calcul que ci-dessous. Cela peut être utile aux autres personnes rencontrant des questions similaires, en particulier si elles traitent avec un très grand nombre de fichiers avec une très grande taille.
Tout d'abord, touchez un join_awk.bash
#!/bin/bash
join -oauto -e0 -a1 $1 $2 | awk '{print $2}'
Par exemple, exécutez ce script Bash pour nom.txt et x.txt
join_awk.bash name.txt x.txt
générerait
1
0
3
2
0
0
Notez que Ici, je ne conservez ici que la deuxième colonne pour économiser de l'espace disque, car dans mon ensemble de données, les premières colonnes sont des noms très longs qui prendraient un espace disque formidable.
Alors simplement implémenter
parallel join_awk.bash name.txt {} \> outdir/output.{} ::: {a,b,c}.txt
Ceci est inspiré de la réponse brillante ci-dessous en utilisant GNU parallel et rejoindre. La différence est que la réponse ci-dessous doit spécifier j1
pour parallel
en raison de sa logique annexe série, ce qui ne le rend pas vraiment "parallèle". En outre, la vitesse deviendra plus lente et plus lente à mesure que l'apaisant en série se poursuit. En revanche, nous manipulons ici chaque fichier séparément en parallèle. Il peut être extrêmement rapide lorsque nous traitons avec un grand nombre de fichiers de grande taille avec plusieurs processeurs.
Enfin simplement fusionner tous les fichiers de sortie à une colonne ensemble par
cd outdir
paste output* > merged.txt
Cela sera également très rapide car paste
est intrinsèquement parallèle.
Avec bash
Du faire:
#!/bin/bash
declare -A hash # use an associative array
for f in "x.txt" "y.txt" "z.txt"; do # loop over these files
while read -r key val; do # read key and val pairs
hash[$f,$key]=$val # assign the hash to val
done < "$f"
done
while read -r key; do
echo -n "$key" # print the 1st column
for f in "x.txt" "y.txt" "z.txt"; do # loop over the filenames
echo -n " ${hash[$f,$key]:-0}" # print the associated value or "0" if undefined
done
echo # put a newline
done < "name.txt"