]]> ]]>

bash

Реализация языка программирования Unix shell

Bourne-again shell (GNU Bash) — это реализация Unix shell, написанная на C в 1987 году Брайаном Фоксом (Brian Fox) для GNU Project.

Синтаксис языка Bash является надмножеством синтаксиса языка Bourne shell. Подавляющее большинство скриптов для Bourne shell могут быть исполнены интерпретатором Bash без изменений, за исключением скриптов, использующих специальные переменные или встроенные команды Bourne shell.

Также синтаксис языка Bash включает идеи, заимствованные из Korn shell (ksh) и C shell (csh): редактирование командной строки, история команд, стек директорий, переменные $RANDOM и $PPID, синтаксис POSIX для подстановки команд: $(…).

Примеры:

Факториал:

Пример для версий Bash 3.0, Bash 3.2.39, Bash 4.0.35, Bash 4.1.5

Используется рекурсивное определение факториала.

function factorial {
    typeset -i n=$1
    if [ $n = 0 ]; then
        echo 1
        return
    fi
    echo $(( n * $(factorial $(( n - 1 )) ) ))
}

for i in {0..16}
do
    echo "$i! = $(factorial $i)"
done

Hello, World!:

Пример для версий Bash 4.0.35, Bash 4.1.5

В этом примере используется инструмент Bash — dc (Desktop Calculator), нестандартный, но часто встречающийся инструмент, позволяющий работать с числами произвольной точности. Команда P (последний символ строки перед | dc) выводит на печать верхний элемент стека. Число до команды в шестнадцатиричном виде выглядит как 0x48656C6C6F2C20576F726C64210A, и пары соседних цифр образуют ASCII-коды символлв строки “Hello, World!”: 0x48 = H, 0x65 = e, 0x6c = l и.т.д. Таким образом, при выводе на печать это число воспринимается как строка.

echo 1468369091346906859060166438166794P | dc

Hello, World!:

Пример для версий Bash 3.0, Bash 4.0.35, Bash 4.1.5
MESSAGE='Hello'
TARGET='World'

echo "$MESSAGE, $TARGET!"

Факториал:

Пример для версий Bash 3.0, Bash 4.0.35, Bash 4.1.5

Используется итеративное определение факториала.

f=1

for (( n=1; $n<=17; $((n++)) ));
do
  echo "$((n-1))! = $f"
  f=$((f*n))
done

Числа Фибоначчи:

Пример для версий Bash 3.0, Bash 4.0.35, Bash 4.1.5

Используется итеративное определение чисел Фибоначчи.

a=0
b=1
 
for (( n=1; $n<=16; n=$n+1 ));
do
  a=$(($a + $b))
  echo -n "$a, "
  b=$(($a - $b))
done
echo "..."

Квадратное уравнение:

Пример для версий Bash 4.0.35, Bash 4.1.5

Сам по себе Bash не работает с числами с плавающей точкой, поэтому для вычисления корней приходится обращаться к bc.

read A;
if [ $A = 0 ]; then
    echo "Not a quadratic equation.";
    exit 0;
fi
read B;
read C;
D=$(( ($B)*($B)-4*($A)*($C) ));
#integer math only!
if [ $D = 0 ]; then
    echo -n "x = "
    echo -e "scale=3\n-0.5*($B)/($A)" | bc
    exit 0;
fi
echo $D
if [ $D -gt 0 ]; then
    echo -n "x1 = "
    echo -e "scale=3\n0.5*(-($B)+sqrt($D))/($A)" | bc
    echo -n "x2 = "
    echo -e "scale=3\n0.5*(-($B)-sqrt($D))/($A)" | bc
else
    echo -n "x1 = ("
    echo -e "scale=3\n-0.5*($B)/($A)" | bc
    echo -n ", "
    echo -e "scale=3\n0.5*sqrt(-($D))/($A)" | bc
    echo ")"
    echo -n "x2 = ("
    echo -e "scale=3\n-0.5*($B)/($A)" | bc
    echo -n ", "
    echo -e "scale=3\n-0.5*sqrt(-($D))/($A)" | bc
    echo ")"
fi

CamelCase:

Пример для версий Bash 4.0.35, Bash 4.1.5

Используются регулярные выражения. Первая строка читает с консоли строку для обработки $text. Вторая — переводит ее в нижний регистр. Затем в полученной строке ищутся последовательности букв — слова — по одному за раз. Каждое слово выделяется (переменная BASH_REMATCH содержит информацию о последовательности символов, которая соответствует регулярному выражению, которое в последний раз искали в строке), заменяется на пробел в исходной строке (во избежание повторного нахождения) и добавляется к результату $cc в нужном регистре (функция ${word^} переводит первый символ аргумента в верхний регистр). Наконец, результат выводится на печать.

read text
text=${text,,}
cc=""
regex='([a-z]+)'
while [[ $text =~ $regex ]]
do
    word=${BASH_REMATCH[1]}
    text=${text/$word/ }
    cc=$cc${word^}
done
echo $cc

Hello, World!:

Пример для версий Bash 3.0, Bash 3.2.39, Bash 4.0.35, Bash 4.1.5, Foma 0.9.17, mksh R40
echo Hello, World!

Факториал:

Пример для версий Bash 3.0, Bash 3.2.39, Bash 4.0.35, Bash 4.1.5, mksh R40

Пример, работающий в версиях Unix shell, не поддерживающих синтаксис for i in {0..16} или ((i = 0; i <= 16; i++)): цикл for конструируется “вручную”.

В mksh используются 32-битовые целые числа, так что для факториалов чисел больше 13 в этой реализации происходит переполнение.

function factorial {
    typeset -i n=$1
    if [ $n = 0 ]; then
        echo 1
        return
    fi
    echo $(( n * $(factorial $(( n - 1 )) ) ))
}

i=0
while [[ $i -le 16 ]] 
do
    echo "$i! = $(factorial $i)"
    ((i++))
done

Комментарии

]]>

blog comments powered by Disqus

]]>

Работа программистам