shell - UNIX shell 脚本中的浮点运算

标签 shell unix math floating-point

如何在 shell 脚本中对 float (例如 1.503923)进行算术运算? float 作为字符串从文件中提取。文件格式如下:

1.5493482,3.49384,33.284732,23.043852,2.2384...
3.384,3.282342,23.043852,2.23284,8.39283...
.
.
.

这是我需要开始工作的一些简化的示例代码。按照算术计算,一切都很好。我从文件中提取一行,然后从该行提取多个值。我认为这会减少搜索处理时间,因为这些文件很大。

# set vars, loops etc.

while [ $line_no -gt 0 ]
do
    line_string=`sed -n $line_no'p' $file_path`  # Pull Line (str) from a file
    string1=${line_string:9:6}                   # Pull value from the Line
    string2=${line_string:16:6}
    string3=...
    .
    .
    .
    calc1= `expr $string2 - $string7` |bc -l     # I tried these and various
    calc2= ` "$string3" * "$string2" ` |bc -l    # other combinations
    calc3= `expr $string2 - $string1`
    calc4= "$string2 + $string8" |bc
    .
    .
    .
    generic_function_call                        # Use the variables in functions
    line_no=`expr $line_no - 1`                  # Counter--
done

我不断得到的输出:

expr: non-numeric argument
command not found

最佳答案

我相信你应该使用:bc

例如:

echo "scale = 10; 123.456789/345.345345" | bc

(这是 Unix 方式:每个工具专门做好它们应该做的事情,并且它们一起工作以完成伟大的事情。不要模仿另一个工具,让它们一起工作。)

输出:

.3574879198

或者使用1而不是10的比例:

echo "scale = 1; 123.456789/345.345345" | bc

输出:

.3

请注意,这不会执行舍入。

如果您需要执行更复杂的操作,我强烈建议切换到 awk,或者切换到 perl 来执行最复杂的操作。

例如:您使用 awk 完成的操作:

# create the test file:
printf '1.5493482,3.49384,33.284732,23.043852,2.2384,12.1,13.4,...\n' > somefile
printf '3.384,3.282342,23.043852,2.23284,8.39283,14.1,15.2,...\n'    >> somefile

# do OP's calculations (and DEBUG print them out!)

awk -F',' '
   # put no single quote in here... even in comments! you can instead print a: \047 
   # the -F tell awk to use "," as a separator. Thus awk will automatically split lines for us using it. 
   # $1=before first ","  $2=between 1st and 2nd ","  ... etc.
    function some_awk_function_here_if_you_want() {  # optionnal function definition
         # some actions here. you can even have arguments to the function, etc.
         print "DEBUG: no action defined in some_awk_function_here_if_you_want yet ..."
    }
    
    BEGIN      {  rem="Optionnal START section. here you can put initialisations, that happens before the FIRST file-s FIRST line is read"
    }
    
    (NF>=8)    {  rem="for each line with at least 8 values separated by commas (and only for lines meeting that condition)"
                  calc1=($2 - $7)
                  calc2=($3 * $2)
                  calc3=($2 - $1)
                  calc4=($2 + $8)
                  # uncomment to call this function :(ex1): #  some_awk_function_here_if_you_want
                  # uncomment to call this script:(ex2): # cmd="/path/to/some/script.sh \"" calc1 "\" \"" calc2 "\" ..." ; rem="continued next line"
                  # uncomment to call this script:(ex2): # system(cmd); close(cmd) 
                  line_no=(FNR-1) # ? why -1? .  FNR=line number in the CURRENT file.   NR=line number since the beginning (NR>FNR after the first file ...)
                  print "DEBUG: calc1=" calc1 " , calc2=" calc2 " , calc3=" calc3 " , calc4=" calc4 " , line_no=" line_no
                  print "DEBUG fancier_exemples: see man printf for lots of info on formatting (%...f for floats, %...d for integer, %...s for strings, etc)"
                  printf("DEBUG: calc1=%d , calc2=%10.2f , calc3=%s , calc4=%d , line_no=%d\n",calc1, calc2, calc3, calc4, line_no)
    }

    END        {  rem="Optionnal END section. here you can put things that need to happen AFTER the LAST file-s LAST line is read"
    }
      
'  somefile # end of the awk script, and the list of file(s) to be read by it.

关于shell - UNIX shell 脚本中的浮点运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14222250/

相关文章:

algorithm - 计算满足要求的可能排列数

java - 埃拉托色尼筛法 ArrayIndexOutOfBounds

c++ - 获取 c/MacOS 中解析 int 命令的输出

postgresql - 将 PostgreSQL SQL 查询结果写入 CSV 格式的 Shell 脚本

javascript - 使用鼠标移动沿斜线移动坐标

linux - 调用存储在另一个 shell 脚本变量中的 shell 脚本

bash - 我们如何根据 unix 中的给定日期获取工作日

java - 获取 shell 命令对 Java 代码的响应

shell - bash中日期乘以分钟

c - 如何在线程/进程之间可移植地共享变量?