2013-08-09 6 views
5

Ho file txt, che sono tutti nella stessa directory. Ognuno ha 2 colonne di dati. Sembrano questo:Come unire più file txt in base alla colonna?

Label1 DataA1
Label2 DataA2
Label3 DataA3

Vorrei utilizzare unirsi per fare un unico file di grandi dimensioni come questo.

Label1 DataA1 DataB1 DataC1
Label2 DataA2 DataB2 DataC2
Label3 DataA3 DataB3 DataC3

Attualmente, ho

unirsi fileA fileB | join - fileC

Tuttavia, ho troppi file per renderlo pratico elencarli tutti - esiste un modo per scrivere un ciclo per questo tipo di comando?

risposta

-1

Basta mettere tutti i file in una cartella e fare

join * | join - /someotherdir/fileC 
+0

Restituisce solo s le istruzioni di utilizzo per il comando join – Justin

+0

non funziona. 'join: manca l'operando dopo' -'' –

0

Questo script si unisce più file insieme (I file sono file*).

#!/bin/bash 
# Create two temp files 
tmp=$(mktemp) 
tmp2=$(mktemp) 
# for all the files 
for file in file* 
do 
    # if the tmp file is not empty 
    if [ -s "$tmp" ] 
    then 
     # then join the tmp file with the current file 
     join "$tmp" "$file" > "$tmp2" 
    else 
     # the first time $tmp is empty, so we just copy the file 
     cp "$file" "$tmp2" 
    fi 
    cp "$tmp2" "$tmp" 
done 

cat "$tmp" 

Ammetto che è brutto, ma sembra funzionare.

2

Con awk si potrebbe fare in questo modo:

awk 'NF > 0 { a[$1] = a[$1] " " $2 } END { for (i in a) { print i a[i]; } }' file* 

Se si desidera ordinare i file:

find -type f -maxdepth 1 -name 'file*' -print0 | sort -z | xargs -0 awk 'NF > 0 { a[$1] = a[$1] " " $2 } END { for (i in a) { print i a[i]; } }' 

volte per (i punti a) popola le chiavi non nell'ordine che sono stati aggiunti in modo da poterli ordinare, ma questo è disponibile solo in gawk. L'idea di mappare le chiavi in ​​un array indicizzato per l'ordine è possibile solo se la colonna 1 non presenta differenze.

gawk 'NF > 0 { a[$1] = a[$1] " " $2 } END { count = asorti(a, b); for (i = 1; i <= count; ++i) { j = b[i]; print j a[j]; } }' ... 
4

Con bash è possibile creare uno script che fa un exec pipe ricorsivo per unirsi:

#!/bin/bash 

if [[ $# -ge 2 ]]; then 
    function __r { 
     if [[ $# -gt 1 ]]; then 
      exec join - "$1" | __r "${@:2}" 
     else 
      exec join - "$1" 
     fi 
    } 

    __r "${@:2}" < "$1" 
fi 

e passare i file come parametri allo script come:

bash script.sh file* 

O un modulo ordinato come:

find -type f -maxdepth 1 -name 'file*' -print0 | sort -z | xargs -0 bash script.sh