Выполнение операции со списком чисел с помощью 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 ответа

Решение

Вы строите не массив, а строку с пробелами. Вместо этого вы можете использовать реальный массив:

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, чтобы избежать появления подоболочки для каждой строки:

#!/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)'))

Использование 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

Скорее что ссылаясь 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[@]}"
Другие вопросы по тегам