Ik probeer bepaalde getallen in een kolom bij elkaar op te tellen met awk
. Ik zou alleen kolom 3 van de “smeden” willen optellen om een totaal van 212 te krijgen. Ik kan de hele kolom optellen met awk
maar niet alleen de “smeden”. Ik heb:
awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt
Ook gebruik ik stopverf. Bedankt voor alle hulp.
smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10
Antwoord
awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename
- De vlag
-F
stelt het veldscheidingsteken in; Ik heb het tussen enkele aanhalingstekens gezet omdat het een speciaal shell-teken is. - Vervolgens past
$1 ~ /smiths/
het volgende {code block} alleen toe op regels waar het eerste veld overeenkomt met de regex/smiths/
. - De rest is hetzelfde als uw code.
Merk op dat aangezien u hier niet echt een regex gebruikt, alleen een specifieke waarde, u net zo gemakkelijk gebruik:
awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename
Welke tekenreeksgelijkheid wordt gecontroleerd. Dit komt overeen met het gebruik van de regex /^smiths$/
, zoals vermeld in een andere antwoord, dat het ^
anker bevat om alleen het begin van de tekenreeks (het begin van veld 1) en het $
anker te koppelen aan alleen overeenkomen met het einde van de string. Ik weet niet zeker hoe bekend je bent met regexes. Ze zijn erg krachtig, maar in dit geval zou je net zo gemakkelijk een stringgelijkheidscontrole kunnen gebruiken.
Opmerkingen
- Trouwens, mijn favoriete awk-referentie is grymoire.com/Unix/Awk.html . Zeer nuttige pagina .
- Bedankt @Wildcard! Ik was in staat om een ongecomprimeerde grootte van bepaalde bestanden netjes samen te voegen in een groot zip-archief op basis van jouw advies 🙂
Answer
Een andere benadering is om awk associatieve arrays te gebruiken, meer info hier . Deze regel produceert de gewenste uitvoer:
awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt
Als neveneffect slaat de array alle andere waarden op:
awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt
Uitvoer:
smiths 212 denniss 100 olivert 10
Reacties
- Dit is het juiste antwoord
Antwoord
Tot dusver zeer goed. Het enige dat u hoeft te doen, is een selector vóór het blok toevoegen om de som toe te voegen. Hier controleren we of het eerste argument alleen “smiths” bevat:
awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Je zou dit een beetje kunnen verkorten door het veldscheidingsteken als een optie op te geven. In awk
is het over het algemeen een goed idee om variabelen op de opdrachtregel te initialiseren:
awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Antwoord
Persoonlijk zou ik de awk
sectie zo eenvoudig mogelijk willen houden en zo veel mogelijk doen zonder . Comingled logic “profiteert niet van de kracht van Unix-pipelines en is daardoor moeilijker te begrijpen, debuggen of aan te passen voor nauw verwante use-cases.
cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}"
Answer
cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}"
-
-F
optie om scheidingsteken op te geven . -
$NF
is voor “laatste kolom”.
Reacties
-
cat
engrep
zijn hier niet nodig. - Waarom is grep niet nodig @Andrey? OP wil alleen " smiths " rijen toevoegen. U ' moet de awk-instructie wijzigen, toch?
- @EL ja, de awk-instructie moet worden gewijzigd in
/smiths/{...}
als de grep-oproep er niet is. Dit is een triviale wijziging, maar het biedt aanzienlijke voordelen: het vermindert het aantal actieve processen, vereenvoudigt de foutcontrole en maakt de code duidelijker.