Come posso combinare i valori da due colonne?


11

Ho un file nel seguente formato:

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

Ora, quello che voglio è ottenere il valore combinato dalle colonne 2 e 3 in ogni riga in modo che i risultati siano i seguenti:

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

Ho provato questo, ma mostra solo l'ultimo valore nel file come il valore 2015-03.

Risposte:


11

Puoi provare a usare awk:

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

Il risultato sarà (suppongo che il valore per il 2015-03 dovrebbe essere 10000):

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

1
Non riesco a credere di aver ricevuto una risposta così rapida: O, non ho mai avuto una risposta così rapida su nessun altro forum :) grazie il comando ha funzionato perfettamente :)
Syed Jahanzaib,

@SyedJahanzaib, se questa risposta ha risolto il problema, ti preghiamo di prendere un momento e accettarlo facendo clic sul segno di spunta a sinistra. Questo segnerà la domanda come risposta ed è il modo in cui i ringraziamenti sono espressi sui siti di Stack Exchange.
terdon

scusa ho dimenticato di contrassegnare la risposta. e grazie anche a tutti gli altri per il tempo prezioso e le risposte, mi hanno aiutato anche a imparare a raggiungere obiettivi con un metodo diverso :)
Syed Jahanzaib,

@SyedJahanzaib, anche se ho guadagnato un bel distintivo per questa risposta, penso che la risposta di Terdon sia più precisa e completa.
Taliezin,

16

Ecco alcuni modi:

  1. Un altro approccio strano

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

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

    o

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell (molto più lento / meno efficiente di quanto sopra)

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

2
$2+=$3potrebbe essere più traballante.
123

@ User112638726 infatti lo è. Grazie.
terdon

3
Puoi anche usarlo in awk '{$2+=$3}NF--'modo che non ci sia ancora un campo vuoto 3 sospeso. Anche se questa è solo la mia preferenza, ed è troppo simile per pubblicare una risposta autonomamente :)
123

1
@ User112638726 ora che non mi era nemmeno venuto in mente. Molto più pulito, grazie!
terdon

Ho scritto questo per te. Nota come non solo in sedqualche modo riesca a capire i campi - anche per definire i campi al volo e i campi con i campi - ma, come sembra essere il caso, l'intero concetto di corrispondenza regexp di Unix si basa in realtà sulla divisione di una stringa in campi secondo uno schema ! Chi lo sapeva?
Mikeserv,

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

... stampe ...

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

Quindi sopra dichiaro un'espressione regolare che definisce un'estensione di campo che consiste in una singola sequenza di caratteri *a lunghezza variabile che ^non sono <spazio> seguita immediatamente da una singola sequenza di caratteri *a lunghezza variabile che è <spazio> . Questa dichiarazione viene applicata allo sedspazio del modello, che è una stringa delimitata (per impostazione predefinita) da ciascun \ncarattere di ewline presente nell'input e che viene ricorsivamente sostituita (per impostazione predefinita) con la successiva per ogni occorrenza della stessa.

L'interfaccia per questa dichiarazione è duplice, e ad ogni livello è completamente regolata e specificata da almeno un comitato internazionale di standard ufficiali IEEE per garantire un'applicazione prevedibile della sedsintassi dei comandi. sedLa sintassi dell'API , ad esempio, viene applicata in questo caso con il comando /address (che è sempre il primo componente di qualsiasi comando ubstitution) , ma il contenuto dello stesso viene interpretato da un'API più semplice come un sottoinsieme di quello specificato per il funzione nella libreria C standard ./sed s///regcomp()

Posso fare queste affermazioni con fiducia, perché sedè non è solo un programma, ma, piuttosto, il file eseguibile compilato chiamato sedsul mio Unix-like macchina è un'implementazione del ben definito, storicamente consolidata, e gli standard-controllato sed applicazione della regolarizzazione del mio sistema librerie corrispondenti all'espressione.


Dalle sedspecifiche:

L' sedutilità deve supportare i BRE descritti nelle espressioni regolari di base XBD ...

... dove troviamo ...

Entrambi BRE e ERE sono supportate dall'interfaccia espressione corrispondente regolare il volume Interfacce Sistema di POSIX.1-2008 sotto regcomp(), regexec()e funzioni relative.

Un'applicazione che chiama regcomp()le presenterà una stringa di pattern e ...

... [t] la sua regcomp()funzione deve compilare l'espressione regolare contenuta nella stringa indicata dall'argomento pattern e posizionare i risultati nella struttura preg ...

Per agire in tal senso, detta applicazione si riferirà quindi alla regcomp()funzione di accompagnamento ...

... [i] regexec()funzione confronta la stringa con terminazione null specificato dalla stringa con l'espressione regolare compilata preg inizializzato da una precedente chiamata a regcomp()...

... regexec()deve riempire gli elementi di [un] array con offset delle sottostringhe di stringa che corrispondono alle \(sottoespressioni tra parentesi \)del modello ... il modello stesso conta come una sottoespressione ...

... [t] la sua regexec()funzione deve compilare tutti gli elementi nmatch di pmatch , dove nmatch e pmatch sono forniti dall'applicazione, anche se alcuni elementi di pmatch non corrispondono a sottoespressioni nel modello .


E così quando lo faccio ...

/[^ ]* */

... sedprima compila l'espressione regolare e memorizza i risultati in memoria, quindi applica l'automa compilato memorizzato lì al contenuto del mio spazio-modello quante volte è necessario per adempiere al mio comando. Ogni volta che lo fa il risultato è una matrice di uno o più campi delimitati da null come delimitati dagli offset restituiti da regexec().

E quando lo faccio ...

//

... per indicare che è necessario utilizzare l'espressione regolare definita più di recente, è sedpossibile chiamare regexec()nuovamente riutilizzando l'espressione regolare precompilata, ma eventualmente applicandola questa volta a un argomento stringa modificato o applicando nuovi parametri nmatch come comando.

Più specificamente ancora ...

  • s/[^ ]* */[&]P/
    • sostituisci la prima occorrenza del modello nello spazio del modello con una [parentesi quadra sinistra, quindi &stessa, quindi una ]parentesi quadra destra seguita da un Pcarattere.
  • s//&+pc/3
    • applicare di nuovo l'ultima espressione regolare utilizzata allo spazio di pattern corrente e sostituire la 3terza occorrenza di pattern nello spazio di pattern con &se stessa seguita dalla stringa aggiunta +pc.

E così per ogni riga di sedinput scrive nel suo stdout, dati i tuoi dati di esempio:

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

Questo potrebbe sembrare strano, ma la dccalcolatrice cita le stringhe nel suo input tra parentesi quadre e il Pcomando stamperà entrambi la parte superiore dello stack senza aggiungere una \newline e successivamente lo farà uscire dallo stack di input.

E così, usando la prima riga lì come esempio, dcfarà:

  • [2015-01 ]P
    • Print e pop la cima dello stack
  • 5000
    • Spingi il numero 5000in cima allo stack e spingi tutti gli elementi attualmente nello stack (ora nessuno) di uno.
  • 1000
    • idem, ma questa volta il numero 5000 nella parte superiore della pila principale viene spinto verso il basso di uno e diventa il secondo elemento sulla pila.
  • +
    • Aggiungi i primi due numeri nello stack insieme, fai saltare entrambi quelli fuori dallo stack e spingi la somma in cima allo stack.
    • Ciò si traduce in uno stack costituito solo dal numero 6000.
    • Questo è un errore di sintassi se uno dei primi due elementi nello stack è una [stringa ].
  • p
    • pstampare la parte superiore dello stack seguita da una \newline aggiunta senza farla fuoriuscire dallo stack.
  • c
    • cimpara la pila

Credo che funzioni, ma non riesco ad analizzarlo. Nel complesso, stai configurando un'aggiunta per DC. Il primo modello ha senso. Penso che corrisponda alla data e agli spazi vuoti finali, ma non capisco cosa fa inserendolo tra parentesi nella classe di caratteri ([&]). Sarebbe bello se lo scrivessi.
Joe,

1
@Joe - c'è di meglio?
Mikeserv,

Wow! Questo ha molto più senso (e mi mostra un sacco di cose di cui ho bisogno per saperne di più.) In particolare, non avevo mai notato l'uso di // per riutilizzare il modello attuale. Questo è il genere di cose che leggi e dimentica fino a quando non ti imbatti in un esempio reale. Molte grazie. Mi ha fatto ridere vedere quanto potere poteva essere racchiuso in un comando minuscolo e quanto ci voleva per spiegarlo.
Joe,

@Joe - beh ... forse sono andato un po 'fuori bordo ...
mikeserv il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.