-
-
Save rindeal/7d87e6a146c1dc95faf5df0978c2c57b to your computer and use it in GitHub Desktop.
A stack implementation, in bash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# A stack, using bash arrays. | |
# | |
# Based on: https://gist.github.com/bmc/1323553 by Brian Clapper (bmc) <[email protected]> | |
# --------------------------------------------------------------------------- | |
# Check if a stack exists | |
# | |
# Usage: stack_exists name | |
stack_exists() { | |
: ${1?'Missing stack name'} | |
local _sname="${1}" | |
eval '_i=$'"_stack_${_sname}_i" | |
[[ -n "${_i}" ]] | |
} | |
# Create a new stack. | |
# | |
# Usage: stack_new name | |
# | |
# Example: stack_new x | |
stack_new() { | |
: ${1?'Missing stack name'} | |
local _sname="${1}" | |
if stack_exists "${_sname}" ; then | |
echo "Stack already exists -- '${_sname}'" >&2 | |
return 1 | |
fi | |
# create main stack array | |
eval "declare -ag _stack_${_sname}" | |
# create stack offset variable | |
eval "declare -ig _stack_${_sname}_i=0" | |
return 0 | |
} | |
# Destroy a stack | |
# | |
# Usage: stack_destroy name | |
stack_destroy() { | |
: ${1?'Missing stack name'} | |
local _sname="${1}" | |
eval "unset _stack_${_sname}"{,_i} | |
return 0 | |
} | |
# Push one or more items onto a stack. | |
# | |
# Usage: stack_push stack item ... | |
stack_push() { | |
: ${1?'Missing stack name'} | |
: ${2?'Missing item(s) to push'} | |
local _sname="${1}" | |
shift 1 | |
local _items=( "${@}" ) | |
if ! stack_exists "${_sname}" ; then | |
echo "No such stack -- '${_sname}'" >&2 | |
return 1 | |
fi | |
eval "local _i=\${_stack_${_sname}_i}" | |
local _item | |
for _item in "${_items[@]}" ; do | |
eval "_stack_${_sname}[${_i}]='${_item}'" | |
let _i+=1 | |
done | |
eval "let _stack_${_sname}_i=${_i}" | |
return 0 | |
} | |
# Print a stack to stdout. | |
# | |
# Usage: stack_print name | |
stack_print() { | |
: ${1?'Missing stack name'} | |
local _sname="${1}" | |
if ! stack_exists "${_sname}" ; then | |
echo "No such stack -- ${_sname}" >&2 | |
return 1 | |
fi | |
echo "Stack '${_sname}':" | |
local val | |
eval "local _i=\${_stack_${_sname}_i}" | |
while (( ${_i} > 0 )) ; do | |
let _i-=1 | |
eval 'val=$'"{_stack_${_sname}[${_i}]}" | |
printf " [%02d] = '%s'\n" \ | |
"$((_i+1))" "${val}" | |
done | |
} | |
# Get the size of a stack | |
# | |
# Usage: stack_size name var | |
# | |
# Example: | |
# stack_size mystack n | |
# echo "Size is $n" | |
stack_size() { | |
: ${1?'Missing stack name'} | |
: ${2?'Missing name of variable for stack size result'} | |
local _sname="${1}" | |
local _rname="${2}" | |
if ! stack_exists "${_sname}" ; then | |
echo "No such stack -- ${_sname}" >&2 | |
return 1 | |
fi | |
eval "${_rname}=\${_stack_${_sname}_i}" | |
} | |
# Pop the top element from the stack. | |
# | |
# Usage: stack_pop name var | |
# | |
# Example: | |
# stack_pop mystack top | |
# echo "Got $top" | |
stack_pop() { | |
: ${1?'Missing stack name'} | |
: ${2?'Missing name of variable for popped result'} | |
local _sname="${1}" | |
local _rname="${2}" | |
if ! stack_exists "${_sname}" ; then | |
echo "No such stack -- ${_sname}" >&2 | |
return 1 | |
fi | |
local _i | |
eval 'let _i=$'"_stack_${_sname}_i" | |
if [[ ${_i} == 0 ]] ; then | |
echo "Empty stack -- ${_sname}" >&2 | |
return 1 | |
fi | |
let _i-=1 | |
eval "${_rname}=\${_stack_${_sname}[${_i}]}" | |
eval "unset _stack_${_sname}[${_i}]" | |
eval "_stack_${_sname}_i=${_i}" | |
return 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment