Zach asked in the chatroom:
I was looking at another interactive shell, murex, and one of the examples given in the README is a pretty cool one liner;
ps aux | select (USER, PID, “%MEM”, COMMAND order by “%MEM” DESC) | head -n 10
Which then takes the output of aux and returns only what we select, and cuts all but 10. Is there any way to reasonably replicate this with Elvish?
I feel the answer is sufficiently interesting and long-form to warrant a forum post:
I looked at Murex’s select and it’s a very cool feature - it supports the full range of SQL syntax because it uses an in-memory SQLite database for it
There isn’t quite something like that in Elvish, but you can always write some good ol’ code to:
- Parse the tabular output of
ps
into a stream of maps - Use Elvish’s functional programming primitives like
order
andtake
to manipulate the data - Format the data back into a table
Something like this:
use re
use str
fn parse-table {
var field-names
each {|line|
if (eq $field-names $nil) {
set @field-names = (re:split '[ \t]+' $line)
} else {
var n = (count $field-names)
# use &max because the last column of ps's output
# (COMMAND) could contain internal whitespaces
var @fields = (re:split '[ \t]+' $line &max=$n)
for i [(range $n)] {
put [$field-names[$i] $fields[$i]]
} | make-map
}
}
}
fn write-table {|fields|
echo (str:join "\t" $fields)
each {|m|
each {|f| put $m[$f]} $fields | str:join "\t" | echo (one)
}
}
ps aux | parse-table |
order &key={|x| put $x[%MEM]} &reverse=$true |
take 10 |
write-table [USER PID %MEM COMMAND]