2012-05-23 22 views
9

Estoy utilizando el comando de unión estándar para unir dos archivos ordenados según la columna1. El comando es simple join file1 file2> output_file.unir varios archivos

¿Pero cómo unir 3 o más archivos usando la misma técnica? join file1 file2 file3> output_file El comando anterior me dio un archivo vacío. Creo que sed puede ayudarme, pero no estoy muy seguro de cómo?

Respuesta

19

man join:

NAME 
     join - join lines of two files on a common field 

SYNOPSIS 
     join [OPTION]... FILE1 FILE2 

sólo funciona con dos archivos.

si necesita unirse a tres, tal vez primero puede unirse a los dos primeros, luego unirse al tercero.

intento:

join file1 file2 | join - file3 > output 

que debe unirse a los tres archivos sin crear un archivo temporal intermedia. - le indica al comando unirse a leer la primera corriente de entrada de stdin

+0

¿Qué quiere decir con un guión para la segunda unión? ¿es un símbolo especial para unirse? –

+0

ver mi actualización. '-' es entendido por muchos programas Unix como abreviatura de stdin/stdout – mata

+0

ya lo consiguió. Gracias. –

0

Unir une líneas de dos archivos en un campo común. Si quieres unirte más, hazlo en parejas. Primero une los dos primeros archivos y luego une el resultado con un tercer archivo, etc.

2

La página man de join indica que solo funciona para dos archivos. Por lo que necesita para crear y archivo intermedio, que se elimina después, es decir .:

> join file1 file2 > temp 
> join temp file3 > output 
> rm output 
+4

O 'unirse a <(unirse fichero2 archivo1) file3' – Kevin

+0

@ Kevin dulce! ¡No sabía eso! – Gnosophilon

9

Uno puede unirse a múltiples archivos (N> = 2) mediante la construcción de una tubería de join s recursiva:

#!/bin/sh 

# multijoin - join multiple files 

join_rec() { 
    if [ $# -eq 1 ]; then 
     join - "$1" 
    else 
     f=$1; shift 
     join - "$f" | join_rec "[email protected]" 
    fi 
} 

if [ $# -le 2 ]; then 
    join "[email protected]" 
else 
    f1=$1; f2=$2; shift 2 
    join "$f1" "$f2" | join_rec "[email protected]" 
fi 
+0

¡Definitivamente mi respuesta favorita!Sin embargo, reemplacé el cuerpo de la función 'join_rec' por este:' f1 = $ 1; f2 = $ 2; cambio 2; if [$ # -gt 0]; entonces; join "$ f1" "$ f2" | join_rec - "$ @"; else; join "$ f1" "$ f2"; fi' como para eliminar la necesidad del segundo 'si'. La llamada se vería como 'join_rec" $ @ "' – user43791

+0

@ack ¿Es posible agregar el nombre del archivo como encabezado en la salida? – user1883491

7

Sé que esto es una vieja pregunta pero para referencia futura. Si sabe que los archivos que desea unir tienen un patrón como en la pregunta aquí, p. Ej. file1 file2 file3 ... fileN A continuación, puede unirse a ellos con este comando

cat file* > output 

donde la producción será la serie de los ficheros adjuntos que se unieron en orden alfabético.

+0

Esto funciona excelente para archivos de texto. ¿Qué hay de los archivos binarios que se han dividido utilizando otros comandos/paquetes/software. –

+2

Bueno, probablemente haya algún encabezado en cada archivo que indica qué tipo de archivo es, por lo que no es suficiente, pero debe buscar otro para preguntas, estoy seguro de que alguien ya lo resolvió – rsz

+2

La pregunta es para unir las filas correspondientes en los archivos de entrada. No concatenándolos. –

3

Creé una función para esto. El primer argumento es el archivo de salida, los argumentos de descanso son los archivos a unir.

function multijoin() { 
    out=$1 
    shift 1 
    cat $1 | awk '{print $1}' > $out 
    for f in $*; do join $out $f > tmp; mv tmp $out; done 
} 

Uso:

multijoin output_file file* 
+0

Gracias, esto fue útil. si alguien quiere agregar el encabezado, sed -i '1i header_text' output_file –