Bash printf не работает для чисел с плавающей запятой

У меня есть сценарий bash, который получает информацию о батарее.

Вот часть этого:

#!/bin/bash

if [ -f /sys/class/power_supply/BAT0/energy_full ]; then
  EF=$( echo $(cat /sys/class/power_supply/BAT0/energy_full)/1000000|bc -l ) 
  [ -n "$EF" ] && printf "energy_full: %0.2f Wh\n" $EF
fi

Этот скрипт работал долго, а потом внезапно перестал работать.

Например, переменная $EF будет содержать 63.71100000000000000000, но вывод printf представляет собой очень длинное число девять строк, которое начинается с -7309889081043958068.

Я пробовал использовать только %f, но безуспешно. Если я использую %d, он напечатает целое число до десятичной точки, но будет жаловаться на недопустимое число.

Я использую тестирование Debian.

GNU bash, версия 5.2.32(1)-выпуск (x86_64-pc-linux-gnu)

С набором -x

+ '[' -f /sys/class/power_supply/BAT0/energy_full ']'
++ bc -l
+++ cat /sys/class/power_supply/BAT0/energy_full
++ echo 63711000/1000000
+ EF=63.71100000000000000000
+ '[' -n 63.71100000000000000000 ']'
+ printf 'energy_full: %0.2f Wh\n' 63.71100000000000000000
energy_full: -nan Wh

Простое добавление printf 'energy_full: %0.2f Wh\n' 63.711 в скрипт приводит к той же ошибке.

Я использую локаль British UK. Раньше скрипт работал.

/bin/printf работает, поэтому я могу использовать его как обходной путь. Вывод: energy_full: 63.71 Wh

Какая это версия Баша? Кроме того, добавьте команду set -x в начало скрипта, чтобы получить трассировку отладки, и посмотрите, что bash думает о команде, которую он выполняет.

Gordon Davisson 06.09.2024 03:19

Я не могу воспроизвести это с помощью bash 5.2.15(1). Какой вывод из cat /sys/class/power_supply/BAT0/energy_full? Проверка -f предполагает, что у вас может возникнуть состояние гонки, поэтому вместо этого выполните Energy_full=$(cat /sys/class/power_supply/BAT0/energy_full) и обработайте ошибку, проверив $?

Allan Wind 06.09.2024 03:32

Пожалуйста, сделайте минимально воспроизводимый пример. Я считаю, что это должно быть так же просто, как ef=63.711; printf "%0.2f\n" $ef

wjandrea 06.09.2024 03:33

Какую локаль вы используете? Я использую французский язык, и мне пришлось заменить точку на запятую, чтобы все работало как положено. В противном случае я получил «строку 4: printf: 63.711: неверный номер» (переведено). Я использую Баш 5.0.

wjandrea 06.09.2024 03:34

Практически никогда не бывает причин использовать $(echo $(command)). Это то же самое, что просто написать $(command)

Barmar 06.09.2024 03:38

printf '%0.2f' 63.71100000000000000000 возвращает -нан? Оно отличается от первоначального значения, которое вы упомянули. А что, если вы просто используете 63 (с точки зрения @wjandrea)?

Allan Wind 06.09.2024 03:39

@Barmar Они перекачивают echo в bc. Тем не менее, я бы использовал следующую строку: bc -l <<< "$(cat ...)/1000000"

wjandrea 06.09.2024 03:39

Это не отвечает на вопрос, но вы можете использовать bc для масштабирования числа вместо строки формата с помощью echo "energy_full: $(echo 'scale=2; 63711000/1000000' | bc -l)"

Allan Wind 06.09.2024 03:45

Пожалуйста, добавьте вывод locale.

Allan Wind 06.09.2024 03:48

Это известная ошибка, патч доступен здесь mail.gnu.org/archive/html/bug-bash/2024-08/msg00027.html

oguz ismail 06.09.2024 03:53

/bin/printf, вероятно, лучший обходной путь.

Allan Wind 06.09.2024 03:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это известная ошибка. Патч доступен здесь: mail.gnu.org/archive/html/bug-bash/2024-08/msg00027.html

comment by oguz ismail

Другие вопросы по теме

Похожие вопросы

Bash с использованием сценария Expect выдает ошибку при вызове ssh
Почему моя программа, запущенная из сценария bash, останавливается, когда сценарий находится в фоновом режиме, но только тогда, когда он получает стандартный ввод из именованного канала?
Когда grep ищет шаблоны в файле с кавычками и/или без кавычек в bash?
Как извлечь столбцы из файла CSV, обработать и создать файл CSV на основе результата извлечения и обработки?
Скрипт Bash, который принимает несколько аргументов пути и проверяет, можно ли там успешно создать файлы
Почему bash не завершает выполнение сценария после ошибки внутри скобок?
Как запустить эмулятор терминала во время работы оболочки?
Как мне отслеживать и уничтожать все процессы, порожденные запуском сценария, не зная имен подпроцессов?
Bash: медленнее использовать zcat по сравнению с cat+zcat или cat+pv+zcat
Как передать переменную оболочки, возвращаемую из Pythonscript, в другую оболочку для запуска другого Pythonscript в правиле Makefile?