Snažím se sečíst určitá čísla ve sloupci pomocí awk
. Chtěl bych sečíst jen sloupec 3 „kovářů“, abych získal celkem 212. Celý sloupec mohu shrnout pomocí awk
, ale nejen „kovářů“. Mám:
awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt
Také používám tmel. Děkujeme za jakoukoli pomoc.
smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10
Odpověď
awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename
- Příznak
-F
nastavuje oddělovač polí; Dal jsem to do jednoduchých uvozovek, protože se jedná o speciální charakter shellu. - Potom
$1 ~ /smiths/
použije následující {kódový blok} pouze na řádky, kde první pole odpovídá regulárnímu výrazu/smiths/
. - Zbytek je stejný jako váš kód.
Všimněte si, že protože zde opravdu nepoužíváte regex, pouze konkrétní hodnotu, můžete stejně snadno use:
awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename
Který kontroluje rovnost řetězců. To odpovídá použití regex /^smiths$/
, jak je uvedeno v jiném odpověď, která obsahuje ^
kotvu, která odpovídá pouze začátku řetězce (začátek pole 1), a $
kotvu pouze porovnejte konec řetězce. Nejste si jisti, jak dobře jste obeznámeni s regulárními výrazy. Jsou velmi silné, ale v tomto případě můžete stejně snadno použít kontrolu rovnosti řetězce.
Komentáře
- Mimochodem, moje oblíbená reference awk je grymoire.com/Unix/Awk.html . Velmi užitečná stránka .
- Děkuji vám @Wildcard! Na základě vaší rady jsem dokázal úhledně agregovat nekomprimovanou velikost konkrétních souborů ve velkém archivu zip 🙂
Odpověď
Dalším přístupem je použití awk asociativních polí, více informací zde . Tento řádek vytváří požadovaný výstup:
awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt
Jako vedlejší efekt pole ukládá všechny ostatní hodnoty:
awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt
Výstup:
smiths 212 denniss 100 olivert 10
Komentáře
- Toto je správná odpověď
Odpověď
Zatím velmi dobrá. Vše, co musíte udělat, je přidat selektor před blok a přidat součet. Zde zkontrolujeme, zda první argument obsahuje pouze „kováře“:
awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Tuto možnost můžete trochu zkrátit zadáním oddělovače polí jako možnosti. V awk
je obecně dobrý nápad inicializovat proměnné na příkazovém řádku:
awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}"
Odpověď
Osobně bych raději udržoval sekci awk
co nejjednodušší a bez ní dělal, co můžete, . Kombinovaná logika nevyužívá sílu unixových kanálů, a je proto těžší ji pochopit, ladit nebo upravit pro úzce související případy použití.
cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}"
Odpověď
cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}"
-
-F
možnost zadat oddělovač . -
$NF
je pro „poslední sloupec“.
Komentáře
-
cat
agrep
jsou zde zbytečné. - Proč je grep nepotřebný @Andrey? OP chce přidat pouze " smiths " řádky. Musíte ' upravit prohlášení awk, že?
- @EL ano, prohlášení awk by mělo být upraveno na
/smiths/{...}
pokud tam není hovor grep. Toto je triviální úprava, ale přináší významné výhody: snižuje počet spuštěných procesů, zjednodušuje kontrolu chyb a činí kód jasnějším.