Sto cercando di sommare determinati numeri in una colonna utilizzando awk
. Vorrei sommare solo la colonna 3 dei “fabbri” per ottenere un totale di 212. Posso sommare lintera colonna usando awk
ma non solo i “fabbri”. Ho:
awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt
Inoltre sto usando lo stucco. Grazie per laiuto.
smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10
Rispondi
awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename
- Il flag
-F
imposta il separatore di campo; Lo metto tra virgolette singole perché è un carattere speciale della shell. - Quindi
$1 ~ /smiths/
applica il seguente {blocco di codice} solo alle righe in cui il primo campo corrisponde alla regex/smiths/
. - Il resto è lo stesso del tuo codice.
Tieni presente che poiché “non stai davvero usando unespressione regolare qui, solo un valore specifico, potresti altrettanto facilmente usa:
awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename
che controlla luguaglianza delle stringhe. Ciò equivale a usare la regex /^smiths$/
, come menzionato in un altro risposta, che include lancora ^
per far corrispondere solo linizio della stringa (linizio del campo 1) e lancora $
solo a corrispondono alla fine della stringa. Non sono sicuro di quanto tu abbia familiarità con le espressioni regolari. Sono molto potenti, ma in questo caso potresti usare un controllo delluguaglianza delle stringhe altrettanto facilmente.
Commenti
- A proposito, il mio riferimento awk preferito è grymoire.com/Unix/Awk.html . Pagina molto utile .
- Grazie @ Wildcard! Sono stato in grado di aggregare ordinatamente una dimensione non compressa di file particolari in un grande archivio zip in base al tuo consiglio 🙂
Risposta
Un altro approccio è usare gli array associativi awk, maggiori informazioni qui . Questa riga produce loutput desiderato:
awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt
Come effetto collaterale, larray memorizza tutti gli altri valori:
awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt
Risultato:
smiths 212 denniss 100 olivert 10
Commenti
- Questa è la risposta giusta
Risposta
Finora molto buona. Tutto quello che devi fare è aggiungere un selettore prima del blocco per aggiungere la somma. Qui controlliamo che il primo argomento contenga solo “smiths”:
awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Puoi accorciarlo un po specificando il separatore di campo come opzione. In awk
è generalmente una buona idea inizializzare le variabili sulla riga di comando:
awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Risposta
Personalmente preferirei mantenere la sezione awk
il più semplice possibile e fare il più possibile senza di essa . La logica Comingled non sfrutta la potenza delle pipeline Unix ed è quindi più difficile da comprendere, eseguire il debug o modificare per casi duso strettamente correlati.
cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}"
Risposta
cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}"
-
-F
opzione per specificare il separatore . -
$NF
è per “ultima colonna”.
Commenti
-
cat
egrep
non sono necessari qui. - Perché grep non è necessario @Andrey? OP desidera aggiungere solo " smiths " righe. ' avresti bisogno di modificare listruzione awk, giusto?
- @EL sì, listruzione awk dovrebbe essere modificata in
/smiths/{...}
se la chiamata grep non è presente. Questa è una modifica banale, ma offre vantaggi significativi: riduce il numero di processi in esecuzione, semplifica il controllo degli errori e rende il codice più chiaro.