AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 698668
Accepted
Sollosa
Sollosa
Asked: 2022-04-11 06:32:38 +0800 CST2022-04-11 06:32:38 +0800 CST 2022-04-11 06:32:38 +0800 CST

corresponda ao valor2 em 2 arquivos se o valor 1 for uma correspondência exata

  • 772

Eu tenho 2 arquivos contendo list. A coluna 1 é userIds e a coluna 2 são valores associados

# cat file1
e3001 75
n5244 30
w1453 500

#cat file2
d1128 30
w1453 515
n5244 30
e3001 55

Coisas a considerar.

  1. userIds podem não ser classificados exatamente em ambos os arquivos
  2. O número de userIds pode variar nos arquivos

REQUERIDOS

  • em primeiro lugar, o userId do arquivo1:column1 deve corresponder ao UserId no arquivo2:column1
  • em seguida, compare seus valores em file1:column2 com file2:column2
  • print onde os valores tem variância. também userIds extras, se houver

RESULTADO:

e3001 has differnece, file1 value: 75 & file2 value: 55
w1453 has differnece, file1 value: 500 & file2 value: 515
d1128 is only present in filename: file1|file2

solução com 1liner-awk ou loop bash é bem-vinda

Estou tentando fazer um loop, mas está cuspindo lixo, acho que há algum erro de lógica

#!/usr/bin/env bash

## VARIABLES
FILE1=file1
FILE2=file2
USERID1=(`awk -F'\t' '{ print $1 }' ${FILE1}`)
USERID2=(`awk -F'\t' '{ print $1 }' ${FILE2}`)
USERDON1=(`awk -F'\t' '{ print $2 }' ${FILE1}`)
USERDON2=(`awk -F'\t' '{ print $2 }' ${FILE2}`)

for user in ${USERID1[@]}
do
    for (( i = 0; i < "${#USERID2[@]}"; i++ ))
    #for user in ${USERID2[@]}
    do
        if [[ ${USERID1[$user]} == ${USERID2[i]} ]]
        then
            echo ${USERID1[$user]} MATCHES BALANCE FROM ${FILE1}: ${USERDON1[$i]} WITH BALANCE FROM ${FILE2}: ${USERDON2[$i]}
        else
            echo ${USERID1[$user]} 
        fi
    done
done

Abaixo está o arquivo copiado diretamente da caixa linux. É separado por tab, mas o awk também funciona com tab, até onde eu sei.

#cat file1
e3001   55
n5244   30
w1453   515
bash shell-script
  • 5 5 respostas
  • 315 Views

5 respostas

  • Voted
  1. Best Answer
    RudiC
    2022-04-11T06:55:33+08:002022-04-11T06:55:33+08:00

    Hmmm - seu roteiro segue a rota cênica, por assim dizer. Que tal uma abordagem simples awk? Curti

    awk '
    NR==FNR         {ARR[$1] = $2
                     F1      = FILENAME
                     next
                    }
    ($1 in ARR)     {if ($2 != ARR[$1]) print $1 " has difference," \
                                              F1 " value: " ARR[$1] \
                                              " & " FILENAME " value: " $2 
                     delete ARR[$1]
                     next
                    }
                    {print $1 " is only present in filename: " FILENAME
                    }
    END             {for (a in ARR) print a " is only present in filename: " F1
                    }
    ' file[12]
    d1128 is only present in filename: file2
    w1453 has difference, file1 value: 500 & file2 value: 515
    e3001 has difference, file1 value: 75 & file2 value: 55
    

    Ele lê todo o arquivo1 em um array, então, com cada linha no arquivo2, verifica $1os índices do array e, se presente, imprime a diferença (ou não imprime se não houver), e deleteé o elemento do array (que deletepode ser ausente em algumas implementações awk, BTW). Se não estiver presente, imprima em conformidade. Na ENDseção, todos os elementos restantes da matriz são impressos, pois existem apenas no arquivo1.

    • 3
  2. terdon
    2022-04-11T07:45:53+08:002022-04-11T07:45:53+08:00

    O shell é uma ferramenta horrível para esse tipo de coisa. Além disso, como regra geral, você deve evitar CAPS para suas variáveis ​​de shell em seus scripts de shell. Como, por convenção, as variáveis ​​de shell do ambiente global são capitalizadas, isso pode levar a colisões de nomenclatura e problemas difíceis de depurar. Finalmente, seu script requer a leitura do arquivo 4 vezes separadas (!) e o processamento dos dados.

    Com isso dito, aqui está outra abordagem awk (francamente, a de RudiC é melhor, mas eu já escrevi isso, então estou postando de qualquer maneira):

    $ awk '{
      if(NR==FNR) {
        fn1=FILENAME;
        f1[$1]=$2;
        next
      }
      f2[$1]=$2;
      if($1 in f1){
        if($2 != f1[$1]){
          printf "%s is different; %s value: %s & %s value: %s\n", \
                 $1,fn1,$2,FILENAME,f1[$1]
        }
      }
      else{
        print $1,"is only present in filename:", FILENAME
      }
    }
    END{
      for(id in f1){
        if( !(id in f2) ){print id,"is only present in afilename:",fn1}
      }
    }' file1 file2
    d1128 is only present in filename: file2
    w1453 is different; file1 value: 515 & file2 value: 500
    e3001 is different; file1 value: 55 & file2 value: 75
    
    • 2
  3. DanieleGrassini
    2022-04-11T08:31:53+08:002022-04-11T08:31:53+08:00

    Os comentários são autoexplicativos:

    awk '
        BEGIN {file1 = ARGV[1]; file2 = ARGV[2]}
    
        # Load all file1 contents
        NR == FNR {map[$1] = $2; next}
        
        # If $1 is not in m then this key is unique to file2
        !($1 in map) {uniq[$1]; next}
    
        # If $1 is in m and the value differs there are delta
        # between the two files. Save it.
        $1 in map && map[$1] != $2 {diff[$1] = $2; next}
    
        # The two files have all the same data.
        {delete map[$1]}
    
        END {
            # Anything is in diff are in both files but
            # with different values
            for ( i in diff )
                print i, "has difference,", file1, "value:", map[i], "&", file2, "value:", diff[i]
    
            # Anything is still in m is only in file 1
            for ( i in map )
                if (!(i in diff))
                    print i, "is only present in filename :", file1
    
            # Anything is in uniq is unique to file2
            for ( i in uniq )
                print i, "is only present in filename :", file2
        }
    ' file1 file2
    
    • 2
  4. αғsнιη
    2022-04-11T08:22:55+08:002022-04-11T08:22:55+08:00
    awk 'function printUniq(Id, fName){
             printf("%s is only present in filename: %s\n", Id, fName)
    }
    
    { fileName[nxtinput+0]=FILENAME }
    !nxtinput{ Ids[$1]=$2; next }
    
    ($1 in Ids){ if($2!=Ids[$1])
                     printf ("%s has difference, %s value: %s & %s value: %s\n",\
                     $1, fileName[0], Ids[$1], fileName[1], $2);
                 delete Ids[$1];
                 next
    }
    { printUniq($1, fileName[1]) }
    END{ for(id in Ids) printUniq(id, fileName[0]) }' file1 nxtinput=1 file2
    
    • 1
  5. Ed Morton
    2022-04-11T11:26:21+08:002022-04-11T11:26:21+08:00

    Essencialmente a mesma solução postada por RudiC, mas sem todos os nomes de variáveis ​​em maiúsculas e com algumas outras pequenas melhorias para clareza:

    $ cat tst.awk
    NR==FNR {
        file1[$1] = $2
        next
    }
    $1 in file1 {
        if ( $2 != file1[$1] ) {
            printf "%s has difference, %s value: %s & value: %s\n", $1, ARGV[1], file1[$1], FILENAME, $2
        }
        delete file1[$1]
        next
    }
    {
        print $1, "is only present in filename:", FILENAME
    }
    END {
        for ( id in file1 ) {
            print id, "is only present in filename:", ARGV[1]
        }
    }
    

    $ awk -f tst.awk file1 file2
    d1128 is only present in filename: file2
    w1453 has difference, file1 value: 500 & value: file2
    e3001 has difference, file1 value: 75 & value: file2
    
    • 1

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • MySQL Select com função IN () com array bash

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve