Pregunta

Estoy procesando un archivo enorme con (GNU) awk , (otras herramientas disponibles son: herramientas de shell de Linux, algunas versiones antiguas (> 5.0) de Perl, pero no puedo instalar módulos ).

Mi problema: si algún campo1, campo2, campo3 contienen X, Y, ZI, debe buscar un archivo en otro directorio que contenga campo4 y campo5 en una línea, e insertar algunos datos del archivo encontrado en la salida actual.

Por ejemplo:

Línea de archivo real:

f1 f2 f3 f4 f5
X  Y  Z  A  B

Ahora necesito buscar otro archivo (en otro directorio), que contenga, por ejemplo,

f1 f2 f3 f4
A  U  B  W

Y escriba a STDOUT $ 0 del archivo original, y f2 y f3 del archivo encontrado, luego procese la siguiente línea de archivo original.

¿Es posible hacerlo con awk ?

¿Fue útil?

Solución

Permítame comenzar diciendo que la descripción de su problema no es tan útil. La próxima vez, sea más específico: es posible que esté perdiendo soluciones mucho mejores.

Por su descripción, entiendo que tiene dos archivos que contienen datos separados por espacios en blanco. En el primer archivo, desea hacer coincidir las tres primeras columnas con algún patrón de búsqueda. Si lo encuentra, desea buscar todas las líneas en otro archivo que contenga la cuarta y la quinta columna de la línea coincidente en el primer archivo. Desde esas líneas, debe extraer la segunda y tercera columnas y luego imprimir la primera columna del primer archivo y la segunda y tercera del segundo archivo. Bueno, aquí va:

#!/usr/bin/env perl -nwa
use strict;
use File::Find 'find';
my @search = qw(X Y Z);

# if you know in advance that the otherfile isn't
# huge, you can cache it in memory as an optimization.

# with any more columns, you want a loop here:
if ($F[0] eq $search[0]
    and $F[1] eq $search[1]
    and $F[2] eq $search[2])
{
  my @files;
  find(sub {
      return if not -f 

Permítame comenzar diciendo que la descripción de su problema no es tan útil. La próxima vez, sea más específico: es posible que esté perdiendo soluciones mucho mejores.

Por su descripción, entiendo que tiene dos archivos que contienen datos separados por espacios en blanco. En el primer archivo, desea hacer coincidir las tres primeras columnas con algún patrón de búsqueda. Si lo encuentra, desea buscar todas las líneas en otro archivo que contenga la cuarta y la quinta columna de la línea coincidente en el primer archivo. Desde esas líneas, debe extraer la segunda y tercera columnas y luego imprimir la primera columna del primer archivo y la segunda y tercera del segundo archivo. Bueno, aquí va:

<*>

A diferencia de la solución de otro póster que contiene muchas llamadas al sistema, esto no recae en absoluto en el shell y, por lo tanto, debería ser bastante rápido.

; # verbatim search for the columns in the file name. # I'm still not sure what your file-search criteria are, though. push @files, $File::Find::name if /\Q$F[3]\E/ and /\Q$F[4]\E/; # alternatively search for the combination: #push @files, $File::Find::name if /\Q$F[3]\E.*\Q$F[4]\E/; # or search *all* files in the search path? #push @files, $File::Find::name; }, '/search/path' ) foreach my $file (@files) { open my $fh, '<', $file or die "Can't open file '$file': $!"; while (defined(

Permítame comenzar diciendo que la descripción de su problema no es tan útil. La próxima vez, sea más específico: es posible que esté perdiendo soluciones mucho mejores.

Por su descripción, entiendo que tiene dos archivos que contienen datos separados por espacios en blanco. En el primer archivo, desea hacer coincidir las tres primeras columnas con algún patrón de búsqueda. Si lo encuentra, desea buscar todas las líneas en otro archivo que contenga la cuarta y la quinta columna de la línea coincidente en el primer archivo. Desde esas líneas, debe extraer la segunda y tercera columnas y luego imprimir la primera columna del primer archivo y la segunda y tercera del segundo archivo. Bueno, aquí va:

<*>

A diferencia de la solución de otro póster que contiene muchas llamadas al sistema, esto no recae en absoluto en el shell y, por lo tanto, debería ser bastante rápido.

= <$fh>)) { chomp; # order of fields doesn't matter per your requirement. my @cols = split ' ',

Permítame comenzar diciendo que la descripción de su problema no es tan útil. La próxima vez, sea más específico: es posible que esté perdiendo soluciones mucho mejores.

Por su descripción, entiendo que tiene dos archivos que contienen datos separados por espacios en blanco. En el primer archivo, desea hacer coincidir las tres primeras columnas con algún patrón de búsqueda. Si lo encuentra, desea buscar todas las líneas en otro archivo que contenga la cuarta y la quinta columna de la línea coincidente en el primer archivo. Desde esas líneas, debe extraer la segunda y tercera columnas y luego imprimir la primera columna del primer archivo y la segunda y tercera del segundo archivo. Bueno, aquí va:

<*>

A diferencia de la solución de otro póster que contiene muchas llamadas al sistema, esto no recae en absoluto en el shell y, por lo tanto, debería ser bastante rápido.

; my %seen = map {(

Permítame comenzar diciendo que la descripción de su problema no es tan útil. La próxima vez, sea más específico: es posible que esté perdiendo soluciones mucho mejores.

Por su descripción, entiendo que tiene dos archivos que contienen datos separados por espacios en blanco. En el primer archivo, desea hacer coincidir las tres primeras columnas con algún patrón de búsqueda. Si lo encuentra, desea buscar todas las líneas en otro archivo que contenga la cuarta y la quinta columna de la línea coincidente en el primer archivo. Desde esas líneas, debe extraer la segunda y tercera columnas y luego imprimir la primera columna del primer archivo y la segunda y tercera del segundo archivo. Bueno, aquí va:

<*>

A diferencia de la solución de otro póster que contiene muchas llamadas al sistema, esto no recae en absoluto en el shell y, por lo tanto, debería ser bastante rápido.

=>1)} @cols; if ($seen{$F[3]} and $seen{$F[4]}) { print join(' ', $F[0], @cols[1,2]), "\n"; } } close $fh; } } # end if matching line

A diferencia de la solución de otro póster que contiene muchas llamadas al sistema, esto no recae en absoluto en el shell y, por lo tanto, debería ser bastante rápido.

Otros consejos

Este es el tipo de trabajo que me hizo pasar de awk a perl en primer lugar. Si va a lograr esto, puede que le resulte más fácil crear un script de shell que cree scripts awk para consultar y luego actualizar en pasos separados.

(He escrito una bestia para leer / actualizar archivos de estilo Windows Ini - es feo. Me gustaría haber usado Perl.)

A menudo veo la restricción " No puedo usar ningún módulo de Perl " ;, y cuando no es una pregunta de tarea, a menudo se debe a la falta de información. Sí, incluso usted puede usar CPAN contiene las instrucciones sobre cómo instalar módulos de CPAN localmente sin tener privilegios de root . Otra alternativa es simplemente tomar el código fuente de un módulo CPAN y pegarlo en su programa.

Nada de esto ayuda si existen otras restricciones no declaradas, como la falta de espacio en el disco que impide la instalación de (demasiados) archivos adicionales.

Esto parece funcionar para algunos archivos de prueba que configuré coincidiendo con sus ejemplos. Sin embargo, involucrar a perl de esta manera (interpuesto con grep) probablemente perjudicará mucho el rendimiento ...

## perl code to do some dirty work

for my $line (`grep 'X Y Z' myhugefile`) {
    chomp $line;
    my ($a, $b, $c, $d, $e) = split(/ /,$line);
    my $cmd = 'grep -P "' . $d . ' .+? ' . $e .'" otherfile';
    for my $from_otherfile (`$cmd`) {
        chomp $from_otherfile;
        my ($oa, $ob, $oc, $od) = split(/ /,$from_otherfile);
        print "$a $ob $oc\n";
    }
}

EDITAR: Use la solución de tsee (arriba), está mucho más bien pensado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top