Значение слишком велико для основы.

Вопрос или проблема

Я пытаюсь отобразить, сколько времени требуется для выполнения моего скрипта в секундах и миллисекундах.

Вот мой код:

#!/bin/bash

before=10#`date +'%s%N'`
sleep 1
after=10#`date +'%s%N'`

echo "$before"

let "time_taken=$before-$after"

echo "$time_taken"

echo "$s"

Но я получаю следующую ошибку:

./tijdsmeting.sh: line 9: let: time_taken=10#1590683503N: value too great for base (error token is "10#15906835
~                              |03N")

Я изучал это и обнаружил, что это связано с десятичными/восьмеричными/… Но я указал, что это должно быть десятичное, использовав #10. Может быть, стоит использовать ibase? И мой токен ошибки не 08, как в других случаях в интернете..

%N является расширением GNU-реализации date (добавлено в 4.5.1 в 2002 году).

Теперь это также поддерживается

  • date от ast-open с версии 2005-01-11
  • busybox date с версии 1.17.0 (2010), хотя это там необязательно и обычно не включено по умолчанию
  • toybox date с версии 0.7.4 (2017).
  • FreeBSD date с 14.1 (2024)

Но, как правило, не другими реализациями.

Здесь, похоже, ваша date не поддерживает %N, и при выполнении date +%N выдает N (такое поведение я могу воспроизвести с FreeBSD до 14.1, и, вероятно, это то, что вы получите и в macos).

Так что:

let "time_taken=$before-$after"

(кстати, имелось в виду after-before) превращается во что-то вроде:

let 'time_taken=10#1590683503N-10#1590683504N'

И bash жалуется на это N, которое не может быть использовано в базе 10.

В любом случае, выполнение date само по себе займет тысячи наносекунд, так что такая точность, вероятно, не имеет смысла.

Здесь вы могли бы переключиться на zsh, где, как и в ksh93, специальная переменная $SECONDS может быть представлена как число с плавающей запятой, и просто сделать:

#! /bin/zsh -
typeset -F SECONDS=0
sleep 1
time_taken=$SECONDS

Или использовать массивную переменную $epochtime модуля zsh/datetime, которая содержит секунды и наносекунды как 2 отдельных целых числа:

#! /bin/zsh -
zmodload zsh/datetime || exit
before=($epochtime)
sleep 1
after=($epochtime)

(( time_taken_ns = 1_000_000_000 * (after[1] - before[1]) + after[2] - before[2] ))

Ответ или решение

Ошибка "Value too great for base" в Bash скрипте: Решение и Объяснение

В вашем скрипте на Bash вы пытаетесь измерить время выполнения скрипта с использованием команды date и выражения для вычисления разности времени. Однако, возникает ошибка value too great for base, что связано с неверным синтаксисом в присвоении значений переменным before и after. Давайте рассмотрим ваш код и внесем необходимые изменения.

Код и Ошибка

Ваш текущий код выглядит так:

#!/bin/bash

before=10#`date +'%s%N'`
sleep 1
after=10#`date +'%s%N'`

echo "$before"
let "time_taken=$before-$after"
echo "$time_taken"

При выполнении этого кода вы получаете ошибку:

./tijdsmeting.sh: line 9: let: time_taken=10#1590683503N: value too great for base (error token is "10#15906835~                              |03N")

Эта ошибка возникает из-за того, что при присвоении значений переменным before и after используется неверный синтаксис. Когда интерпретатор Bash пытается обработать выражение 10#1590683503N, он не распознает N как допустимый символ в десятичной системе счисления.

Решение

Чтобы устранить ошибку, вам необходимо исправить присвоение значений. Вот исправленный вариант вашего скрипта:

#!/bin/bash

# Получаем время в наносекундах
before=$(date +%s%N)
sleep 1
after=$(date +%s%N)

# Время выполнения в наносекундах
time_taken=$(( after - before ))

# Преобразуем в миллисекунды
time_taken_ms=$(( time_taken / 1000000 ))

# Печатаем результат
echo "Время выполнения: $time_taken наносекунд ($time_taken_ms миллисекунд)"

Объяснение Исправлений

  1. Использование $(…) вместо 10#:
    Изменение before=10#... на before=$(...) позволяет корректно получить значение времени без ошибок интерпретации.

  2. Корректное вычисление времени выполнения:
    Мы используем встроенные арифметические операции Bash для вычисления разности after - before и храним результат в time_taken.

  3. Конвертация в миллисекунды:
    Для удобства вы также можете дополнительно вывести время выполнения в миллисекундах, деля результат на 1,000,000.

Заключение

Ваш исправленный скрипт теперь корректно вычисляет время выполнения, не вызывая ошибок. Помните, что использование точного времени выполнения может иметь смысл в контексте ваших задач, но имейте в виду, что сам вызов date может добавить некоторые накладные расходы, поэтому полученные значения могут варьироваться.

Если у вас возникнут дополнительные вопросы или вам нужна помощь в других аспектах скриптов на Bash, не стесняйтесь задавать. Успехов в программировании!

Оцените материал
Добавить комментарий

Капча загружается...