Machine learning with Unix pipes
jott.live
jott.live
It extended Unix design with archives, control lists and matrices and enabled really flexible unix-like processing. For example, recognition of a dataset looks like this:
extract-wav scp:list.scp ark:- | compute-mfcc-feats ark:- ark:- | lattice-decoder-faster final.mdl HCLG.fst ark:- ark:- | lattice-rescore ark:- ark:'|gzip -c > lat.gzip'
Another example is gstreamer command line.
cat /usr/share/dict/words | grep -e '^a..$' | wc -l
can be shortened to grep -cx 'a..' /usr/share/dict/words
but yeah, author probably just wanted to show pipe example. I usually show `du -sh -- * | sort -h` for such cases.grep -cx version:
for i in {1..100}
do
grep -cx 'a..' /usr/share/dict/words
done
cat version: for i in {1..100}
do
cat /usr/share/dict/words | grep -e "^a..$" | wc -l
done
(adding a | tr -d " " to the cat version to make the output equivalent only adds about .1s to the total run). $ time for i in {1..100}; do grep -cx 'a..' /usr/share/dict/words; done > f1
real 0m0.249s
user 0m0.207s
sys 0m0.046s
$ time for i in {1..100}; do cat /usr/share/dict/words | grep -e '^a..$' | wc -l; done > f2
real 0m0.306s
user 0m0.386s
sys 0m0.141s
Edit: probably because your word file is similar to the one in the post? I've got only 39 matching lines from a 102401 line word file.I also put each version in a separate file, so my time commands were time ~/a and time ~/b, and I let the output go to stdout
Also, weirdly, the commands you provided don't print the results from the time command - I'm not sure why (I never use zsh, it's just on the computer I'm using at the moment).
On an x86 MBP:
$ time (for i in {1..100}; {grep -cx 'a..' /usr/share/dict/words}) >/dev/null
user=9.22s system=0.34s cpu=94% total=10.097
$ time (for i in {1..100}; {grep -e '^a..$' /usr/share/dict/words | wc -l}) >/dev/null
user=6.14s system=0.52s cpu=95% total=6.948
$ time (for i in {1..100}; {cat /usr/share/dict/words | grep -e '^a..$' | wc -l}) >/dev/null
user=6.29s system=0.80s cpu=100% total=7.024Before:
<input.txt sed ... | awk ...
After: <input.txt grep bar | sed ... | awk ..
Every new pipeline stage is just "command args |" and you insert it after the end of a previous command, treating the initial input redirect as the end of zeroth command <input.txt | grep bar | sed ... | awk ..
but not in bash cat [file] | less # | grep [ex]
... to quickly check the output of the unprocessed data, before uncommenting again. This is not possible with `grep [ex] [file]`.The power of this of course shines the most when having really long pipes, of up to or over 10 parts (which I've had lots of in my career).
(Addendum: Well, I of course actually have an alias s='less -S' to make this even more fluent, so I do:
cat [file] | s # | grep [ex]
... to peek into various parts of a pipeline. -S is for not folding long lines.)P.S. - do not search for 'cat abuse' to understand this mentality. Rookie error.
That sounds like shell abuse via bloat.
Now we only need to remove the other 100% of the bloat in the shell ;)