LINUX.ORG.RU

Некорректное сравнение числовой переменной zsh

 , , ,


0

2

Здравствуйте! Не справился с формулированием вопроса в гугле, поэтому надеюсь что тут смогут или формулировку подсказать, или же сразу ответить по сабжу, заранее извиняюсь за тривиальность вопроса. Итак! Решил я в правом промте zsh вывести заряд аккумулятора ноутбука. И посмотрев на унылую белую надпись понял, что надо бы её раскрасить. Общий вид функции принимает примерно следующий вид (фрагмент из .zshrc):

for color in red green yellow blue magenta cyan black white; do
    eval $color='%{$fg_no_bold[${color}]%}'
    #eval ${color}_bold='%{$fg_bold[${color}]%}'
done

reset="%{$reset_color%}"
#Индикатор заряда в правом промте
#
function getChargeLevel(){
batteryStatus=$(acpi -b | awk "{print $1}" | sed 's/\([^:]*\): \([^,]*\), \([0-9]*\)%.*/\2/')
batteryChargeLevel=$(acpi -b | awk "{print $1}" | sed 's/\([^:]*\): \([^,]*\), \([0-9]*\)%.*/\3/') 
if [[ ${batteryChargeLevel} > 90 ]] ; then 
colorBatteryStatus=${green}
fi

if [[ ${batteryChargeLevel} > 40 && ${batteryChargeLevel} < 90 ]] ; then 
colorBatteryStatus=${yellow}
fi

if [[ ${batteryChargeLevel} < 40 ]] ; then 
colorBatteryStatus=${red}
fi

if [[ ${batteryChargeLevel} == 100 ]] ; then
colorBatteryStatus=${blue}
fi

echo "${colorBatteryStatus}Battery : ${batteryChargeLevel} , ${batteryStatus}" # right prompt with time

}

setopt prompt_subst
RPROMPT='${cyan}[$(getChargeLevel)${cyan}]'

И все бы ничего, НО! Если убрать из скрипта эту часть :

if [[ ${batteryChargeLevel} == 100 ]] ; then
colorBatteryStatus=${blue}
fi

То скрипт окрашивает правый промт в красный! Однако ситуация становится еще интереснее, когда заряд ниже 100 - в этом случае все работает как положено, то есть от 99 до 90 - зеленая окраска, ниже - желтая.

Начал грешить на то, что регулярка при 100% цепляет какой-нибудь пробел или еще чего - нет же! Выполнил в шелле:

$batteryChargeLevel=$(acpi -b | awk "{print $1}" | sed 's/\([^:]*\): \([^,]*\), \([0-9]*\)%.*/\3/')
$echo a${batteryChargeLevel}a
$a100a  

Так же выполнил 2 условия - результаты привели меня в замешательство:

┌┌(ukio@ukio)-(10:02-:-06/12)┌-¨-¨¨˙
└┌(~)┌¨˙if [[ ${batteryChargeLevel} == 100 ]] ; then
echo "a"
else
echo "b"
fi

a

┌┌(ukio@ukio)-(10:06-:-06/12)┌-¨-¨¨˙
└┌(~)┌¨˙if [[ ${batteryChargeLevel} > 70 ]] ; then
echo "a"
else
echo "b"
fi

b

Шелл перезапускал. Неужели 100 меньше чем 70? Быть ведь такого не может, особенно когда 99 больше 70 (по крайней мере по мнению интерпретатора). Огромная благодарность и плюс к карме всем небезразличным.


http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html:
string1 > string2
true if string1 comes after string2 based on ASCII value of their characters.

batteryStatus=$(acpi -b | awk «{print $1}» | sed 's/\([^:]*\): \([^,]*\), \([0-9]*\)%.*/\2/')
batteryChargeLevel=$(acpi -b | awk «{print $1}» | sed 's/\([^:]*\): \([^,]*\), \([0-9]*\)%.*/\3/')

Ты действительно хочешь на каждую введёную команду дважды вызывать subshell с несколькими вызовами внешних программ?

reset=«%{$reset_color%}»

zsh поддерживает форматирование и цвета в prompt конструкциями вида %F{10}, смешивать их и цвета из autoload colors - моветон

disarmer ★★★ ()
Ответ на: комментарий от disarmer

Ты действительно хочешь на каждую введёную команду дважды вызывать subshell с несколькими вызовами внешних программ?

А какая разница, если они выполняются мгновенно (меньше 0.1 сек)?

Xenius ★★★★★ ()
Ответ на: комментарий от Xenius

Или не выполняются. Или их нет. Или у них сменился синтаксис. И количество вывода с set -x увеличивается.

И зачем добровольно себе тормоза увеличивать на 100ms, если можно то же сделать без них?

disarmer ★★★ ()
Ответ на: комментарий от disarmer

Как? Настроить индикатор батареи средствами иксов? Можно, да...

Xenius ★★★★★ ()
Ответ на: комментарий от Xenius

Вся нужная информация есть в /sys/class/power_supply/BAT*, читать файлы можно встроенными командами zsh. Я ноутами очень редко пользуюсь, у меня готового сниппета для zsh нет, только для awesome

disarmer ★★★ ()

[[ batteryChargeLevel -eq 100 ]] или (( batteryChargeLevel == 100 )).

anonymous ()

Прикинь, а «70» < «9»
Прочитай про сравнение в bash/sh/zsh.

anonymous ()
Ответ на: комментарий от disarmer

В том то и дело, что у меня сейчас только ноут, у которого периодически отходит зарядка. По поводу цветов - выдрал фрагмент с какого-то блога, спасибо за подсказку, буду смотреть. А еще периодически бывает такое, что нужно сидеть вообще под tty - там даже иксов нет. Ежели есть еще способ как-нибудь выводить результат выполнения функции в промт, чтобы тот обновлялся с течением времени (а то без сабшелла если я запустил терминал с 70% заряда - то столько там все время и будет показывать, ничего удивительного!), то я бы с радостью этим способ воспользовался. А можно поподробнее про сниппет? Я просто сейчас как раз себе awesome поставил недавно, думаю как тут все утроено. А если есть еще (не вики!) хороший разбор по конфигам и вообще механике библиотек этого самого awesome - вообще буду очень признателен. Но это, конечно, по возможности.

Ukio ()
Ответ на: комментарий от Ukio

В том то и дело, что у меня сейчас только ноут, у которого периодически отходит зарядка

Тащемта тогда лучше написать демона, который будет мониторить /sys/class/power_supply/BAT*/status и сигнализировать(хоть в PC Speaker), когда значение станет Discharging, а не тормозмть себе шелл.

Singularity ★★★★ ()
Ответ на: комментарий от Singularity

Но я хочу красивый и модный шелл :с Тем более что тормоза в производительности я не сказал бы что замечаю. (будто бы демон намного меньше будет съедать ресурсов)

Ukio ()
Ответ на: комментарий от anonymous

Помогло, только что ноут зарядил, заключение в двойные круглые скобки корректно работает! Спасибо!

Ukio ()

if [[ ${batteryChargeLevel} > 40 && ${batteryChargeLevel} < 90 ]] ; then

if [[ ${batteryChargeLevel} -gt 40 && ${batteryChargeLevel} -lt 90 ]] ; then

Ну ты понял.

Psych218 ★★★★★ ()
Ответ на: комментарий от Psych218

А в чем суть квадратных и круглых скобок? Вся соль в этом же получается.

Ukio ()
Ответ на: комментарий от Ukio

Ежели есть еще способ как-нибудь выводить результат выполнения функции в промт, чтобы тот обновлялся с течением времени

Зачем в prompt это пихать, это никак не связано с выполнением команд и должно обновляться. Если нужно в терминале, поставь tmux, он умеет что угодно на панельке показывать и обновлять с заданным интервалом.

А можно поподробнее про сниппет?

local w_battery=wibox.widget.textbox()         
local bg_battery=wibox.widget.background()     
bg_battery:set_widget(w_battery)               
if awful.util.file_readable('/sys/class/power_supply/BAT0/charge_now') then                    
        local t_battery = timer({ timeout = 60 })
        local cb_battery=function ()           
                local charge=slurp('/sys/class/power_supply/BAT0/charge_now')/slurp('/sys/class/power_supply/BAT0/charge_full')                                                                
                w_battery:set_text(math.floor(100*charge) .. '%')
                if charge<0.2 then
                        bg_battery:set_bg("ff0000")
                else
                        bg_battery:set_bg("000000")
                end
        end
        t_battery:connect_signal("timeout", cb_battery)
        t_battery:start()
        cb_battery()
end
return w_battery
disarmer ★★★ ()
Ответ на: комментарий от Ukio

Есть такая команда test, она же [. Почитай man test. Двойная квадратная скобка — башизм с чуть расширенным синтаксисом (позволяет не принимать переменные за файлы, использовать &&, не экранировать <>). Двойная круглая скобка — тоже башизм, но специально для арифметики в стиле C, там можно использовать C-подобный синтаксис, присваивать значения переменным и т. п. Например в баше можно ((n=1; n++; n>2)) и даже ((n = a<0?10:20)). Есть ещё $(( )), это не башизм, но там просто выражения.

Psych218 ★★★★★ ()
Последнее исправление: Psych218 (всего исправлений: 2)
Ответ на: комментарий от Psych218

Круто! Спасибо за информацию, пойду читать/размышлять!

Ukio ()
Ответ на: комментарий от anonymous

[[ batteryChargeLevel -eq 100 ]] или (( batteryChargeLevel == 100 ))

Это в данном случае одно и тоже, первое быстрее, так как во второе надо тоже в [ или [[ помещать. Ну а в первое ещё $ впереди нужен.

vodz ★★★★★ ()
Ответ на: комментарий от disarmer

Ругается, кстати, на фрагмент кода уже ПОСЛЕ вашего когда.

  <eof> expected near"if" 

Ukio ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.