Полагается ли сценарий на такие зависимости, как Python или Ruby? Им также потребуются разрешения. Вы можете проверить это с помощью:
run-parts /etc/cron.hourly -v
и проверьте, нет ли ошибок. Запустите от имени пользователя root, так как это uid, с которым работает cron.
При печати не -целые числа преобразуются в десятичное строковое представление с использованием специальной переменной OFMT
, которая по умолчанию содержит спецификацию формата printf
(%.6g
). Вы можете изменить его на %.17g
, чтобы получить максимальную точность двоичных чисел двойной точности IEEE 754 с плавающей запятой (, которая используется внутри большинства awk
реализаций в большинстве систем ). Другая переменная(CONVFMT
)используется в других случаях, когда числа с плавающей запятой неявно преобразуются в строки (, например, когда вы объединяете число с чем-то другим )
Вы не получите большей точности с этими двойниками, нет смысла выходить за пределы 17. Уже с 17 вы, вероятно, увидите некоторые артефакты. 15 значащих цифр могут быть лучше, если вам не нужна такая точность.
$ awk -v OFMT=%.17g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981000000008
$ awk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}' < file
6.7088981
Хотя OFMT
влияет на все печатаемые числа с плавающей запятой, вы также можете использовать printf
напрямую для печати чисел с требуемой точностью.
$ awk -F ',' '{SUM+=$2};END{printf "%.15g\n", SUM}' < file
6.7088981
Реализация GNU awk
, начиная с версии 4.1.0, также может быть скомпилирована с поддержкой арифметики произвольной точности (, см. info gawk 'Arbitrary Precision Arithmetic'
). Если это так в вашей системе, вы также можете сделать:
gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}' < file
Пример:
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -v OFMT=%.15g -F ',' '{SUM+=$2};END{print SUM}'
999999999999999945575230987042816
$ printf 'x,%s\n' 1 1000000000000000000000000000000000.00000000001 |
> gawk -M -v PREC=256 -v OFMT=%.60g -F ',' '{SUM+=$2};END{print SUM}'
1000000000000000000000000000000001.00000000001
Другой подход здесь может состоять в том, чтобы использовать bc
(, предполагая, что эти числа всегда выражаются так (0.001
, а не 1e-3
, например)):
<file tail -n+2 | # skip header
cut -d, -f2 | # extract second field
paste -sd + - | # join input lines with +
bc
Количество цифр после .
будет максимальным в любой входной записи.
GNU datamash отображает число с нужной точностью с настройками вывода по умолчанию:
$ datamash --header-in -t, sum 2 < test.txt
6.7088981
Или awk с другим OFMT
более точным:
$ awk -F, -v OFMT='%.10g' '{sum += $2} END { print sum }' test.txt
6.7088981
, но см. Is Floating -Point Math Broken? . Количество цифр после запятой, когда число с плавающей запятой отображается с основанием 10, не всегда соответствует представлению IEEE754 с основанием 2, которое (использует большинство )компьютеров.
Как уже обсуждалось, арифметика с плавающей запятой представляет собой проблему при попытке получить интуитивно понятный ответ, но если вы знаете, что ваш ввод может содержать до, скажем, 3 цифр перед «.» и, скажем, 9 после него, вы можете преобразовать свои числа в десятичные числа, используя манипуляции со строками, затем суммировать их, чтобы избежать проблемы с арифметикой с плавающей запятой, а затем снова преобразовать результат обратно в FP перед печатью, например.:
$ cat tst.awk
BEGIN {
FS = ","
bef = 3
aft = 9
}
NR>1 {
split($2,f,".")
val = sprintf("%*s%-*s",bef,f[1],aft,f[2])
gsub(/ /,0,val)
sum += val
}
END {
sub(".{"aft"}$",".&",sum)
sub(/0+$/,"",sum)
print sum
}
$ awk -f tst.awk file
6.7088981
Если 3 и/или 9 не являются для вас достаточно большими числами, выберите другие числа или выполните подход за 2 -прохода, который вычисляет максимальное значение для каждого на первом проходе, например.:
$ cat tst.awk
BEGIN { FS = "," }
FNR==1 { next }
{ split($2,f,".") }
NR==FNR {
bef = (length(f[1]) > bef ? length(f[1]) : bef)
aft = (length(f[2]) > aft ? length(f[2]) : aft)
next
}
{
val = sprintf("%*s%-*s",bef,f[1],aft,f[2])
gsub(/ /,0,val)
sum += val
}
END {
sub(".{"aft"}$",".&",sum)
sub(/0+$/,"",sum)
print sum
}
$ awk -f tst.awk file file
6.7088981