Yeah the existing wheels suck so I don't blame them for reinventing it. Often it is easier to write a proper program to do exactly what you want than to figure out the arcane `sed | xargs` command from the 70s that nobody has ever bothered to make vaguely usable.
Here's a program I wrote to count matches in a very large file. I wonder how long it would take to work out the equivalent bash command.
use aho_corasick::AhoCorasick;
use std::fs::File;
use std::io::BufReader;
fn main() {
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 3 {
eprintln!("Usage: ./count_occurances 'pattern' <filename>");
return;
}
let f = File::open(&args[2]).expect("Error opening input file");
let reader = BufReader::new(f);
let patterns = &[&args[1]];
let ac = AhoCorasick::new(patterns);
let count = ac.stream_find_iter(reader).count();
println!("{}", count);
}
I didn't downvote you, but I'm guessing you're being downvoted because the answer is just "grep -c", which counts matches instead of printing them, and I discovered that in about ten seconds by googling "grep count matches". (I actually didn't know about that option, though! I'd have reflexively used "grep | wc -l" to count matched lines, because I know that wc is what you use to count things.)
Ah. Yes, that's fair, grep -c counts matching lines, not matches - which is something I've never actually run into as an issue, so I didn't know about it.
On further Googling (about a minute this time, with a few different pages) I found that 'grep -o' would do the trick (and someone beat me to it, above.)
I'd still argue that one minute of Googling would be quicker than writing a program to do the same.
The program took me about 10 minutes to write. I think that's pretty good compared to the googling and finding out that `-c` doesn't work (which I also did).
Plus it's written in a robust language. The `grep | wc` solution here looks ok, but in my experience bash hacks tend to be full of bugs, especially around quoting, whitespace, etc.
Fwiw I would first reach for grep -c but that has the wrong semantics here as it counts matching lines. I think rg -c is the same but IIRC it also has a --count-matches flag which does what you want. But I don’t think that invalidates your point; I think I got lucky and happened to know how to do this already. And it may be that your program is faster anyway (or that it adapts well if you have multiple patterns)
No objections at all to people building simpler UIs for common tasks. The classic Unix tools are like table saws without labels or safety features - confusing and rightfully intimidating. You have to read the manual carefully to avoid chopping off digits.
... but they're also like table saws in that once you know them well and are comfortable with the usage patterns that protect you from the dangerous parts, they let you achieve things with a minimum of fuss and ceremony.
Ah, thanks for clarifying. I did indeed misunderstand.
grep -o $pattern $filename | wc -l
would work in that case, I think.
I did have to think for a minute to come up with that version. It was definitely still much faster for me than writing my own matching logic would have been, but that may well be different for other people.
Here's a program I wrote to count matches in a very large file. I wonder how long it would take to work out the equivalent bash command.