【问题标题】:Float calculation on csv in bashbash中csv的浮点计算
【发布时间】:2015-12-26 21:59:00
【问题描述】:

我想用

评估单个列
$(echo "1023630 / ln( 10000 /$2 )  / ( 3435 / ln( 10000 /$2 ) - 298 )" | bc -l)

但在读取文件时会抛出语法错误。我该如何评估这个? 我试过了

while IFS="," read a b c d; do 
    printf "%s,%s,%s,%s\n" $a $(echo "1023630 / ln( 10000 /$b )  / ( 3435 / ln( 10000 /$b ) - 298 )" | bc -l) $c $d; 
done < abcdtemp.csv 

150918021814,1421.5,1,
(sRuntime error (func=(main), adr=26): Function ln not defined.
150918021216,1421.5,1.4,

即使使用 awk 也无法正常工作

awk -F',' -v OFS="," '{$2=$(echo "1023630/ln(10000/$2)  / (3435/ln(10000/$2)-298)" | bc -l);$3=$(echo "1023630/ln(10000/$3)  / (3435/ln(10000/$3)-298)" | bc -l);}1' file

awk -F',' -v OFS="," '{$1;$2=printf "%.1f\n","1023630/ln(10000/$2)/(3435/ln(10000/$2)-298)";$3=printf "%.1f\n","1023630/ln(10000/$2)/(3435/ln(10000/$3)-298)";}1' file

任何提示或帮助,我错过了什么?谢谢。

【问题讨论】:

    标签: bash csv awk


    【解决方案1】:

    您的$2 可能为空(或某些无效值)。

    bc 中的自然对数也是l,而不是ln

    最后,在您的 awk 示例中,代码位于撇号中,因此根本不会评估 $2

    【讨论】:

    • 嗯,我想知道究竟是什么“为你工作”。例如,您不应为此使用bc,并且不应将 awk 括在双引号中以使 $2 扩展。上面有正确答案的提示,但如果你做错事只是因为它给了你在这种情况下所期望的输出,我不会感到惊讶。
    • @EdMorton 实际上我使用了错误的变量,而不是 $a,$b,$c,$d。我错误地使用了 1 美元、2 美元、3 美元、4 美元。愚蠢的错误,当你如此愤怒地寻找解决方案时。它对我有用,而 IFS="," 阅读 a b c d;做 printf "%s,%s,%s,%s\n" $a $(echo "1023630 / l( 10000 /$b ) / ( 3435 / l( 10000 /$b ) - 298 )" | bc - l) $c $d;完成
    • 这是一个非常缓慢、复杂且容易出错的解决方案。如果您在问题中发布了示例输入和预期输出,并且在提出问题后 25 分钟内没有接受答案,我相信有人可以很快向您展示更好的方法,但我现在已经做出了自己的输入并针对它运行你的脚本以获得预期的输出并发布一个 awk 答案。
    【解决方案2】:

    您只需要一个简单的 awk 脚本:

    $ cat file
    3,5,7,11
    
    $ while IFS="," read a b c d; do printf "%s,%s,%s,%s\n" $a $(echo "1023630 / l( 10000 /$b ) / ( 3435 / l( 10000 /$b ) - 298 )" | bc -l) $c $d; done < file
    3,874.94898530684189106603,7,11
    
    $ awk 'BEGIN{FS=OFS=",";OFMT="%.20f"} {d=log(10000/$2); print $1, 1023630 / d / (3435/d - 298), $3, $4}' file
    3,874.94898530684179149830,7,11
    

    它比 shell 循环更高效、更健壮、更便携,而且在其他方​​面都更好。小数点后第 12 位后的输出值差异可能无关紧要,并且是由于工具之间的浮点算术差异造成的。

    如果您不确定,请查看在仅 1,000 行长的文件上运行每个命令需要多长时间,

    $ time while IFS="," read a b c d; do printf "%s,%s,%s,%s\n" $a $(echo "1023630 / l( 10000 /$b ) / ( 3435 / l( 10000 /$b ) - 298 )" | bc -l) $c $d; done < file_1k > /dev/null
    real    0m39.066s
    user    0m7.433s
    sys     0m24.458s
    
    $ time awk 'BEGIN{FS=OFS=",";OFMT="%.20f"} {d=log(10000/$2); print $1, 1023630 / d / (3435/d - 298), $3, $4}' file_1k > /dev/null
    real    0m0.060s
    user    0m0.031s
    sys     0m0.031s
    

    【讨论】:

    • 感谢您的逻辑和优化。
    猜你喜欢
    • 2019-08-10
    • 2012-03-10
    • 1970-01-01
    • 2022-01-07
    • 2012-04-29
    • 1970-01-01
    • 2011-01-10
    • 2021-09-01
    • 2014-01-10
    相关资源
    最近更新 更多