Bash
SSV/CSV 操作:計算比率
請注意,我知道
datamash
並且是一位經驗豐富的awk
使用者。我正在尋找比awk
. 假設我有以下內容:// data_file foo bar biz 10 100 1000 11 150 990 10 95 1010 9 99 950
// usage goal, in pseudo code cat data_file | <tool> --ratio foo,bar --ratio foo,biz --ratio bar,biz
// desired output foo bar biz foo_bar foo_biz bar_biz 10 100 1000 0.1 0.01 0.1 11 150 990 0.073 0.011 0.1515 10 95 1010 0.105 0.0099 0.094 9 99 950 0.09 0.0095 0.1042
為了得到這個介面,我將用 C++ 建構一些微不足道的東西。
在此之前,在 Unix 中是否有一個解決方案?
使用幾個 bash 函式,如果你有一個文件可以使用
paste
,你可以非常簡單地到達那裡:bc``csvtool
div() { printf "%1.4f\n" $(bc -l <<<"1.0 * $1 / $2") } export -f div ratio() { echo "$1"_"$2" csvtool -t ' ' namedcol $1,$2 data.ssv | tail -n+2 | csvtool call div - } paste -d ' ' <(cat data.ssv) <(ratio foo bar) <(ratio foo biz) <(ratio bar biz) | csvtool -t ' ' readable -
輸出:
foo bar biz foo_bar foo_biz bar_biz 10 100 1000 0.1000 0.0100 0.1000 11 150 990 0.0733 0.0111 0.1515 10 95 1010 0.1053 0.0099 0.0941 9 99 950 0.0909 0.0095 0.1042
如果您真的想以流媒體方式進行,您最好的選擇可能是
awk
,例如:解析.awk
# Parse the requested column ratios into dividend[] and divisor[] # by column name BEGIN { split(ratios_str, ratios, / +/) for(r in ratios) { split(ratios[r], cols, /,/) dividend[++i] = cols[1] divisor[i] = cols[2] } } # Sort out the header NR == 1 { # Create the ColumnName-to-ColumnNumber hash split($0, a); for(k in a) c2n[a[k]]=k # Print the header line printf "%s ", $0 for(i=1; i<=length(dividend); i++) printf "%s_%s ", dividend[i], divisor[i] printf "\n" } NR > 1 { printf "%s ", $0 for(i=1; i<=length(dividend); i++) printf "%1.4f ", $(c2n[dividend[i]]) / $(c2n[divisor[i]]) printf "\n" }
像這樣執行它:
<data.ssv awk -f parse.awk -v ratios_str='foo,bar foo,biz bar,biz' | column -t
輸出:
foo bar biz foo_bar foo_biz bar_biz 10 100 1000 0.1000 0.0100 0.1000 11 150 990 0.0733 0.0111 0.1515 10 95 1010 0.1053 0.0099 0.0941 9 99 950 0.0909 0.0095 0.1042
使用米勒(https://github.com/johnkerl/miller)並執行
mlr --pprint put '$foo_bar=$foo/$bar;$foo_biz=$foo/$biz;$bar_biz=$bar/$biz' input >output
你有
foo bar biz foo_bar foo_biz bar_biz 10 100 1000 0.100000 0.010000 0.100000 11 150 990 0.073333 0.011111 0.151515 10 95 1010 0.105263 0.009901 0.094059 9 99 950 0.090909 0.009474 0.104211