【问题标题】:How to multiply small numbers in Bash如何在 Bash 中乘以小数
【发布时间】:2016-07-04 03:47:07
【问题描述】:

我想将数组中的所有条目与3.17 * 10^-7 之类的数字相乘,但 Bash 不能这样做。我尝试使用awkbc,但它不起作用。如果有人可以帮助我,我将不胜感激。

输入数据示例(总共4000个数据文件):

TecN210500-0100.plt
TecN210500-0200.plt
TecN210500-0300.plt
TecN210500-0400.plt
......

这是我的代码:

#!/bin/bash

ZS=($(find . -name "*.plt")) 
i=1

Variable=$(awk "BEGIN{print 10 ** -7}")
Solutiontime=$(awk "BEGIN{print 3.17 * $Variable}")

for Dataname in ${ZS[@]}
do
    Cut=${Dataname:13}
    Timesteps=${Cut:0:${#Cut}-4}
    Array[i]=$Timesteps 
    i=$((i++))
    p=$((i++))
done

Amount=$p

for ((i=1;i<10;i++))
do
    Array[i]=${i}00
done

for (($i=1;i<$Amount+1;i++))
do
    Array[i]=$(awk "BEGIN{print ${Array[i]} * $Solutiontime}")
done

Array[0]=Solutiontime

第一个循环: 提取 e.i. “0100”。

第二个循环: “删除”前导零 -> e.i. “100”

最后一个循环: 乘以时间步 -> e.i. "100 * 3.17*10^-7"

【问题讨论】:

  • 不,伙计,这段代码难以辨认。请通过缩进四个空格来改进格式。另见Help Center
  • 这将永远不会增加 $i: i=$((i++)) -- 因为您使用的是 post-increment 运算符,返回值是 previous i 的值分配给 i++ 已经是赋值运算符了,坚持使用((i++)); p=$i
  • 感谢您的建议!
  • 那么您只是根据文件名TecN210500-0100.plt 查找输出,而不是从文件中读取任何内容吗?
  • 是的,只是文件名

标签: arrays bash shell awk


【解决方案1】:

awk 来救援!

awk 'BEGIN{print 3.17 * 10^-7 }'

3.17e-07

迭代 1

awk -F'[-.]' '{printf "%s %e\n",substr($1,5),$2*3.17*10^-7}' file

210500 3.170000e-05
210500 6.340000e-05
210500 9.510000e-05
210500 1.268000e-04

用于作为输入的发布文件名。

迭代 2

如果您只需要计算出来的数字,只需删除第一个字段

awk -F'[-.]' '{printf "%e\n",$2*3.17*10^-7}' file

3.170000e-05
6.340000e-05
9.510000e-05
1.268000e-04

这将是脚本的输出。我强烈建议您在 awk 脚本中移动您拥有的任何逻辑,而不是使用数组在 shell 级别上工作。

【讨论】:

  • 如果我这样做,数组的条目很奇怪。即300 1,7e-06。在这个位置上它应该是 3.17e-05,因为操作是 100*3,17*10^-7。
  • 请在您的原始帖子中发布具有代表性的输入数据。否则就是猜测。您最初的问题是如何将我展示的3.17 * 10^-7 加倍。
  • 我已经从流体动力学程序“fluent”中导出了数据文件。文件名是“TecN210500-xxxxx.plt”。 “xxxxx”是迭代步骤。第一个循环从文件名中提取迭代步骤。但前 9 个数据文件是“TecN210500-0100.plt”; “TecN210500-0200.plt”......所以前导零必须删除。第二个循环删除前导零。最后一个循环将每个迭代次数与时间步长相乘。结果将是求解时间。希望现在清楚了。
  • 我并不是说这是答案,但这是您想要实现的目标吗?
  • 我不理解您发布的代码,但是是的,这就是我想要实现的目标......如果您能告诉我如何在我的代码中实现这一点,我将不胜感激。我希望它在一个没有前导数字 210500 的数组中。
【解决方案2】:

对文件名进行一点parameter expansion 修整,然后让awk 为您计算。

#!/bin/bash
for f in *.plt; do
    num=${f##*-}   # remove the stuff before the final -
    num=${num%.*}  # remove the stuff before the last .
    num=${num#0}   # remove the left-hand zero
    awk "BEGIN {print $num * 3.17 * 10**-7}"
done

或者,完全使用awk

#!/bin/bash
for f in *.plt; do
    awk -v f="$f" 'BEGIN {gsub(/^TecN[[:digit:]]+-0?|.plt$/, "", f); print f  * 3.17 * 10**-7}'
done

【讨论】:

  • 非常感谢。这很好用。如何在不覆盖最后一步的情况下将每个步骤保存到文件中?
  • 我知道了:awk "BEGIN {print $num * 3.17 * 10**-7}" &gt;&gt; File.txt 如果我需要更多信息,可以再次询问。
猜你喜欢
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 2014-11-10
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多