Вы можете легко реализовать стек, используя массив.
Обратите внимание, что bash не является объектно-ориентированным, поэтому нет способа написать mystack.doSomething()
, как это было бы в C ++. Вместо этого вы должны передать имя стека в качестве параметра функции: doSomething myStack
. Если вам нужен только один стек, вы можете жестко закодировать имя стека внутри функций, что упрощает процесс.
Один глобальный стек
#! /bin/bash
stack=()
push() { stack+=("$@"); }
peek() { printf %s\\n "${stack[-1]}"; }
pop() { peek; unset 'stack[-1]'; }
Использование интерактивного примера. $
- это приглашение:
$ push a b
$ push c
$ peek
c
$ pop
c
$ pop
b
$ pop
a
$ pop # stack is empty, results in error
-bash: unset: [-1]: bad array subscript
Несколько стеков
#! /bin/bash
push() { local -n "stack=$1"; shift; stack+=("$@"); }
peek() { local -n "stack=$1"; printf %s\\n "${stack[-1]}"; }
pop() { peek "$1"; unset "$1[-1]"; }
Интерактивный пример использования. $
- это приглашение:
$ push stack1 a
$ push stack2 b
$ peek stack1
a
$ peek stack2
b
Другие операции
Помните, что стеки - это обычные массивы. Такие функции, как size
или search
могут быть реализованы путем прямого доступа к массиву. Например, для размера stack
записать ${#stack[@]}
.
Альтернативный подход: несколько стеков в одном ассоциативном массиве
До сих пор каждый стек использовал свой собственный массив. Вы должны удостовериться, чтобы избежать конфликтов имен с остальной частью вашего сценария. Поскольку переменная для каждого стека использует имя стека (первый аргумент после push
/ peek
/ pop
), в стеках могут быть только имена, принятые bash (например, stack1
, но не stack 2
, 3rdStack
, .
или ""
). В качестве альтернативы вы можете хранить все стеки в одном ассоциативном массиве (также известном как карта). Однако вы потеряете прямой доступ к массиву, поэтому реализация дополнительных методов может оказаться более сложной:
#! /bin/bash
declare -A stacks=()
size() { local j="${stacks[.$1]}"; printf %d\\n "${j/-*/0}"; }
lastindex() { local i="$(size "$1")"; echo "$((i - 1))"; }
push() { local j="$(size "$1")"; stacks["$j.$1"]="$2"; stacks[".$1"]="$((j+1))"; }
peek() { local i="$(lastindex "$1")"; printf %s\\n "${stacks[$i.$1]}"; }
pop() { local i="$(lastindex "$1")"; peek "$1"; unset "stacks[$i.$1]"; stacks[".$1"]="$i"; }
Это только базовая c реализация. Вы можете использовать только sh один элемент за раз, то есть вы должны написать push stackname a; push stackname b
вместо push stackname a b
. peek
или pop
в пустом стеке ничего не делают, кроме вывода пустой строки.