Como posso combinar valores de duas colunas?


11

Eu tenho um arquivo no seguinte formato:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

Agora, o que eu quero é obter o valor combinado das colunas 2 e 3 em cada linha para que os resultados sejam os seguintes:

2015-01   6000
2015-02   8000
2015-03   9000

Eu tentei isso, mas ele mostra apenas o último valor no arquivo, como o valor 2015-03.

Respostas:


11

Você pode tentar usar awk:

awk '{ print $1, $2 + $3; }' /tmp/raw

O resultado será (suponho que o valor para 2015-03 seja 10000):

2015-01 6000
2015-02 8000
2015-03 10000

1
Eu não posso acreditar que eu tenho a responder a esta rápida: O, I nunca se tal resposta rápida em qualquer outro fórum :) obrigado o comando funcionou perfeitamente :)
Syed Jahanzaib

@SyedJahanzaib, Se esta resposta resolveu seu problema, reserve um momento e aceite-o clicando na marca de seleção à esquerda. Isso marcará a pergunta como respondida e é assim que os agradecimentos são expressos nos sites do Stack Exchange.
terdon

desculpe, esqueci de marcar a resposta. e obrigado todos os outros também porque há um tempo valioso e respostas, que me ajudou muito no aprendizado de alcançar objetivos com método diferente :)
Syed Jahanzaib

@SyedJahanzaib, embora tenha ganhado um bom emblema por esta resposta, acho que mais precisa e abrangente é a resposta de Terdon.
taliezin

16

Aqui estão algumas maneiras:

  1. Outra abordagem inábil

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    ou

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell (muito mais lento / menos eficiente que o anterior)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3pode ser mais complicado.
123

@ User112638726 de fato é. Obrigado.
terdon

3
Você também pode usar awk '{$2+=$3}NF--'para que ainda não exista um campo em branco 3. Embora isso seja apenas a minha preferência, e seja muito semelhante a postar como resposta por si só :) #
123 #

1
@ User112638726 agora que nem sequer me ocorreu. Muito mais arrumado, obrigado!
terdon

Eu escrevi isso para você. Observe como, de sedalguma maneira, não apenas consegue entender os campos - mesmo para definir campos em movimento e campos com campos - mas, como é aparentemente o caso, todo o conceito de correspondência de regexp do Unix é realmente baseado na divisão de uma sequência em campos de acordo com um padrão ! Quem sabia?
mikeserv

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

... imprime ...

2015-01   6000
2015-02   8000
2015-03   10000

Então, acima, declaro uma expressão regular que define uma extensão de campo que consiste em uma sequência única de caracteres de *tamanho variável que ^não é <espaço>, seguida imediatamente por uma sequência única de caracteres de *tamanho variável que é <espaço> . Essa declaração é aplicada ao sedespaço do padrão de, que é uma string delimitada (por padrão) por cada \ncaractere de linha de ew que ocorre na entrada e que é recursivamente substituída (por padrão) pelo próximo para cada ocorrência do mesmo.

A interface desta declaração é dupla e, em cada nível, é totalmente regulamentada e especificada por pelo menos um comitê oficial internacional de padrões do IEEE, para garantir a aplicação previsível da sedsintaxe de comando. sedA sintaxe da API , por exemplo, é aplicada neste caso com o comando /address (que é sempre o primeiro componente de qualquer comando ubstitution) , mas o conteúdo do mesmo é interpretado por uma API mais básica como um subconjunto do especificado para o comando função na biblioteca C padrão ./sed s///regcomp()

Eu posso fazer essas declarações com confiança, porque nãosed é apenas um programa, mas o executável compilado nomeado em minha máquina tipo Unix é uma implementação do aplicativo bem definido, estabelecido historicamente e controlado por padrões das aplicações regulares do meu sistema. bibliotecas correspondentes à expressão.sedsed


Das sedespecificações:

O sedutilitário deve suportar os BREs descritos em Expressões regulares básicas do XBD ...

... onde encontramos ...

Ambas as ERBs e EREs são suportados pela interface Expressão Matching regular no volume do sistema Interfaces de POSIX.1-2008 sob regcomp(), regexec()e funções relacionadas.

Um aplicativo que chama regcomp()apresentará uma sequência de padrões e ...

... [a] regcomp()função deve compilar a expressão regular contida na string apontada pelo argumento padrão e colocar os resultados na estrutura preg ...

Para agir sobre isso, o referido aplicativo se referiria à regcomp()função complementar de ...

... [a] regexec()função compara a string terminada em nulo especificada por string com a expressão regular compilada preg inicializada por uma chamada anterior para regcomp()...

... regexec()deve preencher os elementos de [uma] matriz com deslocamentos das substrings de string que correspondem às \(subexpressões entre parênteses \)do padrão ... o próprio padrão conta como subexpressão ...

... [a] regexec()função deve preencher todos os elementos nmatch de pmatch , onde nmatch e pmatch são fornecidos pelo aplicativo, mesmo que alguns elementos de pmatch não correspondam a subexpressões no padrão .


E então quando eu faço ...

/[^ ]* */

... sedprimeiro compila a expressão regular e armazena os resultados na memória e, em seguida, aplica o autômato compilado armazenado ali ao conteúdo do meu espaço de padrão quantas vezes for necessário para executar meu comando. Toda vez que o resultado é feito, há uma matriz de um ou mais campos delimitados por nulo, conforme delimitados nas compensações retornadas por regexec().

E quando eu faço ...

//

... para indicar que a expressão regular definida mais recentemente deve ser usada, sedbasta chamar regexec()novamente reutilizando a expressão regular pré-compilada, mas possivelmente aplicando-a desta vez a um argumento de string alterado ou aplicando novos parâmetros nmatch como eu comando.

Mais especificamente ainda ...

  • s/[^ ]* */[&]P/
    • substitua a primeira ocorrência de padrão no espaço do padrão por um [colchete esquerdo, depois &ele próprio, depois um ]colchete direito seguido de um Pcaractere.
  • s//&+pc/3
    • aplique a última expressão regular usada novamente ao espaço padrão atual e substitua a 3terceira ocorrência de padrão no espaço padrão por &si mesma, seguida pela sequência anexada +pc.

E assim, para cada linha de sedentrada, ela grava em seu stdout, dados seus dados de exemplo:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

Isso pode parecer estranho, mas a dccalculadora cita as seqüências de caracteres entre colchetes e o Pcomando imprime a parte superior da pilha sem anexar uma linha de \new e depois a retira da pilha de entrada.

E assim, usando a primeira linha lá como exemplo, dcfará:

  • [2015-01 ]P
    • PRint e pop no topo da pilha
  • 5000
    • Empurre o número 5000na parte superior da pilha e empurre todos os elementos atualmente na pilha (agora nenhum) para baixo em um.
  • 1000
    • idem, mas desta vez o número 5000 na parte superior da pilha principal é pressionado por um e se torna o segundo elemento na pilha.
  • +
    • Adicione os dois números principais da pilha juntos, retire os dois da pilha e empurre a soma para o topo da pilha.
    • Isso resulta em uma pilha que consiste apenas no número 6000.
    • Este é um erro de sintaxe se um dos dois principais elementos da pilha for uma [sequência ].
  • p
    • ppenteie o topo da pilha seguido por uma linha de e- \nmail anexada sem retirá-la da pilha.
  • c
    • caprenda a pilha

Acredito que funcione, mas não posso analisá-lo. No geral, você está configurando uma adição para o DC. O primeiro padrão faz sentido. Eu acho que combina com a data e os espaços em branco à direita, mas não entendo o que colocar isso dentro dos colchetes da classe de caracteres ([&]). Seria ótimo se você explicasse isso.
21315 Joe

1
@ Joe - melhor?
mikeserv

Uau! Isso faz muito mais sentido (e me mostra um monte de coisas sobre as quais preciso aprender mais.) Em particular, nunca havia notado o uso de // para reutilizar o padrão atual. Esse é o tipo de coisa que você lê e esquece até encontrar um exemplo real. Muito obrigado. Isso me fez rir ao ver quanta energia poderia ser transformada em um comando minúsculo e quanto era necessário para explicá-lo.
21415 Joe

@Joe - bem ... talvez eu tenha exagerado um pouco ...
mikeserv
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.