Durante a leitura de um arquivo, escolha campos específicos e compare-os com outro arquivo no Unix bash?

1

Eu tenho um arquivo CSV que contém as colunas a, b, c, dee, e outro arquivo que contém a coluna z. Ao ler linha por linha a partir do primeiro arquivo eu quero apenas os campos c e d e ao mesmo tempo eu quero comparar d com z do segundo arquivo.

z é um significado variável, for i in catfileb do ...... . Agora, se d é o mesmo que z, então exiba z, mas se eles forem diferentes, então sempre exiba "pin". Mas se z é, por exemplo, o maior ou menor display "lon" ou "sma".

Arquive um:

a b c d e
1 2 2 3 3
3 4 6 5 9
4 5 0 9 9

Arquivo b:

z
3
1
8

Então c, d e z são variáveis, então eu estava pensando em dois loops. Ao ler o arquivo linha por linha a, obtenha c e d, compare com z.

    
por user2613272 31.07.2013 / 12:30

2 respostas

1

Supondo que você queira comparar linhas em file b com linhas correspondentes em file a (ou seja, que ambos os arquivos tenham o mesmo número de linhas e você esteja comparando linha por linha), use um script Perl para faça isso por você:

#!/usr/bin/perl
$file_a = "/path/to/file_a";
$file_b = "/path/to/file_b";
open $fa,'<',$file_a or die "Failed to open file $file_a: $!\n";
open $fb,'<',$file_b or die "Failed to open file $file_b: $!\n";
@file_a = <$fa>;
@file_b = <$fb>;
close $fa;
close $fb;
for (0..$#file_a){
    ($col_c,$col_d) = (split / /,$file_a[$_])[2,3];
    $col_z = $file_b[$_];
    $to_display = "$col_c $col_d";
    if($col_z eq $col_d){
        $to_display .= " $col_z";
    }
    else{
        $to_display .= " pin";
        if ($col_z gt $col_c and $col_z gt $col_d ){
            $to_display .= " lon";
        }
        elsif($col_z lt $col_c and $col_z lt $col_d) {
            $to_display .= " sma";
        }
    }
    print "$to_display\n";
}

Salve o arquivo acima como /path/to/myscript (depois de modificar os locais de file_a e file_b em seus locais verdadeiros), torne-o executável: chmod +x /path/to/myscript e finalmente invoque-o: $ /path/to/myscript .

    
por 31.07.2013 / 12:58
1

Como eu disse no meu comentário, não tenho certeza do que você está tentando fazer, você parece querer sempre imprimir os campos c e d e comparar somente d com z . Em caso afirmativo, a solução abaixo deve funcionar.

$ paste a b | awk '{print $3,$4,$6}' | head -n 1; paste a b | tail -n +2 |
   while read a b c d e z; do 
    echo -n "$c $d"; 
    if [ "$d" -lt "$z" ]; then 
      echo "pin sma"; 
    elif [ "$d" -gt "$z" ]; then 
      echo "pin lon"; 
    else echo $z; 
    fi; 
   done 

Execute nos arquivos de exemplo que você forneceu, isso dá:

c d z
2 33
6 5pin lon
0 9pin lon

Explicação

Como você quer uma comparação aritmética, os cabeçalhos quebrarão o script. No entanto, imagino que você gostaria de tê-los na saída final. Então, primeiro eu os imprimo:

paste a b | awk '{print $3,$4,$6}' | head -n 1;

Então, agora queremos processar o restante dos campos, ignorando o cabeçalho. Então, nós paste os arquivos novamente, pule os cabeçalhos ( tail -n +2 ) e processe os campos.

    
por 31.07.2013 / 18:04