使用bc对数字列表执行操作而不使用循环

时间:2017-08-29 15:25:27

标签: bash bc

我有一个我想在BASH中执行操作的数字列表(例如sine,sqrt等)。目前,我在空间" "上使用bc和大头钉环绕数字向量,这看起来有点笨重:

x=`seq 1 2.5 30`  # generate a list of numbers
for i in $x ; do 
  a=${a}`echo "sqrt($i)" | bc`" "
done # a is output vector

我想知道是否有更简洁的方法可以在不使用循环和" "标记的情况下执行此操作?

3 个答案:

答案 0 :(得分:2)

您没有构建数组,而是一个包含空格的字符串。您可以使用实际的数组:

for x in $(seq 1 2.5 30); do
    a+=( $(bc <<< "sqrt($x)") )
done

printf '%s\n' "${a[@]}"

导致

1
1.8
2.4
2.9
3.3
3.6
4.0
4.3
4.5
4.8
5.0
5.3

或者,您可以在bc中完全编写它,以避免为每行产生子shell:

#!/usr/bin/bc

for (x = 1; x <= 30; x += 2.5) {
    sqrt(x)
}
quit

如果您将其填充到名为getsquares的脚本中,则可以使用

获取数组
a=($(./getsquares))

或者两全其美(bc的单个实例,嵌入在Bash脚本中):

a=($(bc <<< 'for (x = 1; x <= 30; x += 2.5) sqrt(x)'))

答案 1 :(得分:1)

而是为每个号码调用bc,您可以使用这样的单个awk:

awk -v b=1 -v e=30 'BEGIN{for (i=b; i<=e; i+=2.5) printf "%.1f\n", sqrt(i)}'
1.0
1.9
2.4
2.9
3.3
3.7
4.0
4.3
4.6
4.8
5.1
5.3

要将输出存储在数组中,请使用:

arr=($(awk -v b=1 -v e=30 'BEGIN{for (i=b; i<=e; i+=2.5) printf "%.1f\n", sqrt(i)}'))

然后使用以下方式打印输出:

printf '%s\n' "${arr[@]}"

答案 2 :(得分:1)

使用bash,特别是mapfile将命令的输出存储到数组中:

$ mapfile -t nums < <(seq 1 2.5 30)

$ mapfile -t sqrts < <(printf "sqrt(%f)\n" "${nums[@]}" | bc -l)

$ printf "%s\n" "${sqrts[@]}"
1
1.87082869338697069279
2.44948974278317809819
2.91547594742265023543
3.31662479035539984911
3.67423461417476714729
4.00000000000000000000
4.30116263352131338586
4.58257569495584000658
4.84767985741632901407
5.09901951359278483002
5.33853912601565560540