66` sumcol ` is a simple unix-style command-line tool for summing numbers from a
77column of text. It's a replacement for the tried and true Unix-isms, like `awk
88'{s += $3} END {print s}'` (prints the sum of the numbers in the third
9- whitespace delimited column), without all the verbosity.
9+ whitespace delimited column), without all the verbosity. ` sumcol ` tries to be
10+ smart and interpret hex, float, and decimal values automatically, though you
11+ can force the radix with the ` --radix ` flag.
1012
1113## Quick Install
1214``` console
13- $ cargo install sumcol
15+ $ cargo install --locked sumcol
1416```
1517
1618## Examples
@@ -32,10 +34,10 @@ Arguments:
3234
3335Options:
3436 -f, --field <FIELD> The field to sum. If not specified, uses the full line [default: 0]
35- -x, --hex Treat all numbers as hex, not just those with a leading 0x
37+ --radix <RADIX> How to interpret numeric input [default: auto] [possible values: auto, hex, decimal]
3638 -d, --delimiter <DELIMITER> The regex on which to split fields [default: \s+]
3739 -v, --verbose Print each number that's being summed, along with some metadata
38- -h, --help Print help
40+ -h, --help Print help (see more with '--help')
3941 -V, --version Print version
4042```
4143
@@ -56,17 +58,20 @@ The size is shown in column -- or field -- number 5 (starting from 1), so we can
5658
5759``` console
5860$ ls -l | sumcol -f5
61+ WARN sumcol: Field index out of range, skipping field=5 line="total 48"
596217469
6063```
61- Which is equivalent to (but shorter than) the classic awk incantation:
64+ The warning is from the ` total 48 ` summary line which doesn't have a fifth
65+ field; it's safely skipped and the sum is still correct. Equivalent to (but
66+ shorter than) the classic awk incantation:
6267``` console
6368$ ls -l | awk ' {s += $5} END {print s}'
646917469
6570```
6671
6772### Sum all input
6873
69- Sometimes you use other tools to extact a column of numbers, in which case you
74+ Sometimes you use other tools to extract a column of numbers, in which case you
7075can still use sumcol with no arguments to simply sum all of the input. Using
7176the file listing from above, we could do the following:
7277
@@ -78,10 +83,10 @@ $ ls -l | awk '{print $5}' | sumcol
7883### Summing hex numbers
7984
8085Programmers are often dealing with numbers written in hex. Typically in forms
81- like ` 0x123abc ` or even simply ` 0000abcd ` . When ` sumcol ` sees a number starting
82- with ` 0x ` it always assumes it's written in hex and parses it accordingly.
83- However, a hex number written without that prefix requires that we tell sumcol
84- to use hex.
86+ like ` 0x123abc ` or even simply ` 0000abcd ` . By default, when ` sumcol ` sees a
87+ number starting with ` 0x ` it assumes it's written in hex and parses it
88+ accordingly. However, a hex number written without that prefix requires that we
89+ tell sumcol to use hex via ` --radix=hex ` .
8590
8691For this example we'll sum the sizes of each section in the compiled ` sumcol `
8792binary. We can see this information with the ` objdump ` command.
@@ -161,47 +166,40 @@ LOAD,
16116600000148
162167```
163168
164- Yuck. That has numbers, and non-numbers. Luckily, ` sumcol ` will easily handle
165- this! It quietly ignores non-numbers treating them as if they're a ` 0 ` . So
166- let's see what answer we get:
169+ Yuck. That has numbers, and non-numbers. The numeric values are hex without a
170+ ` 0x ` prefix, so we need to pass ` --radix=hex ` to tell ` sumcol ` to parse them as
171+ hex. Non-numeric tokens (table headers, comma-separated description tags) will
172+ emit warnings and be treated as ` 0 ` :
167173
168174``` console
169- $ objdump -h target/release/sumcol | sumcol -f3
170- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "0014c350". Consider using -x
171- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "000003b4". Consider using -x
172- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "0004f458". Consider using -x
173- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "0000cae8". Consider using -x
174- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "000087c8". Consider using -x
175- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "0002e5e0". Consider using -x
176- [2023-11-10T21:02:06Z WARN sumcol] Failed to parse "0002c9c0". Consider using -x
177- 732
175+ $ objdump -h target/release/sumcol | sumcol -f3 --radix=hex
176+ WARN sumcol: Failed to parse as hex, treating as 0 clean_str="format"
177+ WARN sumcol: Field index out of range, skipping field=3 line="Sections:"
178+ WARN sumcol: Failed to parse as hex, treating as 0 clean_str="Size"
179+ WARN sumcol: Stripped commas from value original="LOAD," clean="LOAD"
180+ WARN sumcol: Failed to parse as hex, treating as 0 clean_str="LOAD"
181+ ... (similar warnings for each header and description line) ...
182+ 0x20C3AC
178183```
179184
180- Interesting. Sumcol quietly ignores non-numbers like ` LOAD ` in the above
181- example, but here it's warning us that it's seeing strings that _ look like_ hex
182- numbers but we didn't tell it to parse the numbers as hex. Let's try again
183- following the recommendation to use ` -x ` .
185+ The warnings here are expected and benign -- ` format ` , ` Size ` , ` LOAD, ` , etc. are
186+ not hex values and contribute ` 0 ` to the sum, so the final answer is correct.
184187
185- ``` console
186- $ objdump -h target/release/sumcol | sumcol -f3 -x
187- 0x20C3AC
188- ```
189- NOTE: If the hex numbers started with a leading ` '0x ` , ` sumcol ` would have
190- silently parsed them correctly and omitted the warning.
188+ If the values had been written with a ` 0x ` prefix, ` sumcol ` would have
189+ auto-detected them as hex with no flag needed.
191190
192191## Debugging
193192
194193If ` sumcol ` doesn't seem to be working right, feel free to look at the code on
195194github (it's pretty straight forward), or run it with the ` -v ` or ` --verbose `
196- flag, or even enable the ` RUST_LOG=debug ` environment variable set. For
197- example:
195+ flag, or run with the ` RUST_LOG=debug ` environment variable set. For example:
198196
199- ``` console:
197+ ``` console
200198$ printf " 1\n2.5\nOOPS\n3" | sumcol -v
201- 1 # n=Integer(1) sum=Integer(1) cnt=1 radix=10 raw_str="1"
202- 2.5 # n=Float(2.5) sum=Float(3.5) cnt=2 radix=10 raw_str="2.5"
203- 0 # n=Integer(0) sum=Float(3.5) cnt=2 radix=10 raw_str="OOPS" err="ParseFloatError { kind: Invalid } "
204- 3 # n=Integer(3) sum=Float(6.5) cnt=3 radix=10 raw_str="3"
199+ 1 # n=Integer(1) sum=Integer(1) radix=Decimal raw_str="1"
200+ 2.5 # n=Float(2.5) sum=Float(3.5) radix=Decimal raw_str="2.5"
201+ 0 # n=Integer(0) sum=Float(3.5) radix=Decimal raw_str="OOPS" err="Failed to parse (use --radix=hex if hex), treating as 0 "
202+ 3 # n=Integer(3) sum=Float(6.5) radix=Decimal raw_str="3"
205203==
2062046.5
207205```
@@ -212,10 +210,9 @@ The metadata that's displayed on each line is
212210| ------| -------------|
213211| ` n ` | The parsed numeric value |
214212| ` sum ` | The running sum up to and including the current ` n ` |
215- | ` cnt ` | The running count of _ successfully_ parsed numbers. If a number fails to parse and 0 is used instead, it will not be included in ` cnt ` |
216- | ` radix ` | The radix used when trying to parse the number as an integer |
213+ | ` radix ` | The effective radix used when parsing the value (` Hex ` or ` Decimal ` ) |
217214| ` raw_str ` | The raw string data that was parsed |
218- | ` err ` | If present, this shows the error from trying to parse the string into a number |
215+ | ` err ` | If present, the warning message from a failed parse |
219216
220217This should be enough to help you debug the problem you're seeing. However, if
221218that's not enough, give it a try with ` RUST_LOG=debug ` .
0 commit comments