вторник, 2 февраля 2010 г.

QuickCalc на BASH

# Filename:/etc/profile.d/rlfuncs.sh
# Some tricks with numbers

[ -z "$BASH_VERSION" ] && exit

2bin(){
    local b= p= i= j=
    let b=10#0$2?10#0$2:16 p=10#0$1 2>/dev/null || p=0
    for ((i=b;i-->0;j=(!(i%8))*2))
    do
        printf %${j}s $[($p>>$i)&1]
    done|tr " " ":"
}

qcalc(){
  local __I_a= __a_I= e= \
        __u=$(tput civis;tput cuu1;tput cuu1;tput ed;tput cnorm)
  echo
  while read -ep Expr\: __a_I;do
    let __I_a=${__a_I:-0} 1 2>/dev/null;e=$?
    printf "${__u}> = d:%-10d x:%-10s o:%#-10o   b:%-20s\n"\
           $__I_a "$(printf "%04X" $__I_a)" "$(printf "%o" $__I_a)" "$(2bin $__I_a)"

    ((e))&&echo -e "$(tput civis;tput bold;tput setaf 5;tput cuu1)\\ \\ \n (--) Err!.."\
                   "$(tput sgr0;tput cnorm)"
  done; echo
}

export -f 2bin qcalc



    Честно говоря, я и сам не знаю зачем, так выделил этот скрипт. Просто, однажды, возникла необходимость, быстро воспроизвести числа в разных системах исчисления. Возможность использовать команду screen есть не всегда. Да и тут хотелось иметь сразу, всё и прямо перед глазами, в т.ч. и "выше-введенные команды". Вот и возникла, изначально, мысль, быренько накидать функционишку, которая, используя синтаксис bash, выдавала бы некий результат....

C этого всё и началось...

    Так возникла функция qcalc. Она изначально, должна была выполнять, лишь, проверку на корректность введенных значений, и в положительном случае выдавать результат вычисления арифметического выражения. Но чем дальше, тем больше, скроллинг тоже немного не устраивал, т.к. в режиме screen особо не прокрутишь скроллер, кто знает тот поймет :). А дальше - больше, возникла необходимость формировать не просто строку бинарного эквивалента, полученного значения, но строку, определенным образом сформированную. Так появилась функция 2bin.

    Что делает qcalc:

  -- определяет локальными, дабы, вдруг, не изменить значения уже существующих переменных: __I_a; __a_I; e; u.

  -- читает в цикле переменную __a_I со стандартного потока ввода пока не "конец ввода"
  -- в переменную __I_a, запихивает результат арифметического вычисления содержимого __a_I, а в переменную "e" кладет результат последнего выполнения (т.е. рез возможной ошибки). Здесь операция let включает режим арифметического разбора, а комбинация {$__a_I:-0}, говорит о том что если вычисление не удалось, то вернуть "0", после пробела стоит "1" - это гарантирует нам общий результат выполнения, как "success", независимо от вычисления __a_I, ну и дальше стнадартный поток ошибки переправляет в /dev/null, дабы не засорять консоль.
   -- Теперь, через printf реализует вывод на экран в основных 4-х системах исчисления: 10, 16, 8, 2. Для вывода двоичных данных использует функцию 2bin.


продолжение следует...