'Creating classes and objects using bash scripting
I'm trying to use bash scripting to make an script act like a phone book, so i tried to create classes and objects but unfortunately i couldn't find a way to do that ! so i'm asking how to create a class using bash scripting??
Solution 1:[1]
You can try to do something like this
example.sh
#!/bin/bash
# include class header
. obj.h
. system.h
# create class object
obj myobject
# use object method
myobject.sayHello
# use object property
myobject.fileName = "file1"
system.stdout.printString "value is"
system.stdout.printValue myobject.fileName
obj.h
obj(){
. <(sed "s/obj/$1/g" obj.class)
}
obj.class
# Class named "obj" for bash Object
# property
obj_properties=()
# properties IDs
fileName=0
fileSize=1
obj.sayHello(){
echo Hello
}
obj.property(){
if [ "$2" == "=" ]
then
obj_properties[$1]=$3
else
echo ${obj_properties[$1]}
fi
}
obj.fileName(){
if [ "$1" == "=" ]
then
obj.property fileName = $2
else
obj.property fileName
fi
}
system.h
. system.class
system.class
system.stdout.printValue(){
echo $($@)
}
system.stdout.printString(){
echo $@
}
Link for reference: https://github.com/mnorin/bash-scripts/tree/master/objects The point is you can't create objects but you can emulate object-oriented programming in bash
Solution 2:[2]
So I remember checking this question and answer a few years back .. and was thinking.... WHAT!?!?!
Then last week I took a closer look at @Maxims answer and then it became clear..
I have spent the last week and created a bash class transpiler and class loader for class object, with methods and other goodies.. all cause I wanted to create a terminal animation infrastructure:
So while this is just a start I found this to be a SUPER cool and challenging adventure.. I hope my code would help someone else as well!!
BTW: Was tested only on MAC OS so some tweaking might be needed :)
Solution 3:[3]
While there's no true way to create classes in Bash, you can get a little creative. I've found over the years that my preferred way to do this is to create a function that returns a command that can be executed to change state or read properties of the instance. The instance data can be stored in an array.
For example, if you wanted to make a class for binary search trees, you could have this in BinarySearchTree.sh:
__BINARYSEARCHTREE_INSTANCE_DATA__=()
__BINARYSEARCHTREE_INSTANCE_DATA_LENGTH__=()
__BINARYSEARCHTREE_INSTANCE_DATA_SIZE__=()
BinarySearchTree()
{
echo "__BinarySearchTree__ $RANDOM "
}
__BinarySearchTree__()
{
local id="$1"
local code="$2"
case "$code" in
'.insert' | '[insert]' | "['insert']" | '["insert"]')
local value="$3"
if [ "${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 0] + set}" ]; then
local length="${__BINARYSEARCHTREE_INSTANCE_DATA_LENGTH__["$id"]}"
local new_node="$length"
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$length"]="$value"
length=$((length + 1))
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$length"]=''
length=$((length + 1))
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$length"]=''
local current_node=0
local parent
while [ 1 ]; do
parent="$current_node"
if [ "$value" -lt "${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node))"]}" ]; then
current_node="${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node + 1))"]}"
if [ "$current_node" == '' ]; then
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((parent + 1))"]="$new_node"
break
fi
else
current_node="${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node + 2))"]}"
if [ "$current_node" == '' ]; then
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((parent + 2))"]="$new_node"
break
fi
fi
done
__BINARYSEARCHTREE_INSTANCE_DATA_LENGTH__["$id"]="$((length + 1))"
__BINARYSEARCHTREE_INSTANCE_DATA_SIZE__["$id"]="$((${__BINARYSEARCHTREE_INSTANCE_DATA_SIZE__["$id"]} + 1))"
else
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 0]="$value"
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 1]=''
__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 2]=''
__BINARYSEARCHTREE_INSTANCE_DATA_LENGTH__["$id"]=3
__BINARYSEARCHTREE_INSTANCE_DATA_SIZE__["$id"]=1
fi;;
'.has' | '[has]' | "['has']" | '["has"]')
local value="$3"
local current_node=0
if [ "${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 0] + set}" ]; then
while [ 1 ]; do
local current_value="${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node))"]}"
if [ "$current_value" == "$value" ]; then
return 0
fi
if [ "$value" -lt "$current_value" ]; then
current_node=${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node + 1))"]}
else
current_node=${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", "$((current_node + 2))"]}
fi
if [ "$current_node" == '' ]; then
return 1
fi
done
else
return 1
fi;;
'.size' | '[size]' | "['size']" | '["size"]')
if [ "${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 0] + set}" ]; then
echo "${__BINARYSEARCHTREE_INSTANCE_DATA_SIZE__["$id"]}"
else
echo 0
fi;;
'.empty' | '[empty]' | "['empty']" | '["empty"]')
if [ "${__BINARYSEARCHTREE_INSTANCE_DATA__["$id", 0] + set}" ]; then
return 1
else
return 0
fi;;
'.clear' | '[clear]' | "['clear']" | '["clear"]')
unset "__BINARYSEARCHTREE_INSTANCE_DATA__[$id, 0]"
esac
}
And then make objects like this:
source './BinarySearchTree.sh'
process()
{
local tree="$1"
$tree.insert 52
$tree.insert -150
$tree.insert 42
if $tree.has 42; then
echo 'Has 42!'
else
echo 'Does not have 42!'
fi
$tree.clear
echo "Size: $($tree.size)"
}
main()
{
local tree=$(BinarySearchTree)
process "$tree"
}
main "$#" "$@"
The advantages of this method are that objects can be passed into other functions and there are no external file operations. Even though this may seem impractical, it actually makes Bash quite a nice language to work in since you can modularize your classes.
Solution 4:[4]
Try with BashX: https://github.com/reduardo7/bashx (This is my project, I use it on several other projects)
Example
#!/usr/bin/env bash
# ...
@Actions.action1() { # \\n Action without arguments
set -x
pwd
@log "
Action 1
Multi-Line
"
ls -la
bash
}
@Actions.action2() { # param1 [param2] \\n Action with arguments\\n\\tdescription second line\\nother line
eval "$(@user.options 'new:-n|-N' 'path:-p|--path:true')"
set -x
@log "'n' or 'N' parameter: ${user_options_new}"
@log "'p' or 'path' parameter: ${user_options_path[@]} (${#user_options_path[@]})"
local param1="$1"
local param2="$2"
[[ "$param1" != 'asd' ]] && @throw.invalidParam param1
@log Action 2
@log Param1: $1
@log Param2: $2
}
@app.run "$@"
Usage
./myscript action1
./myscript action2 -n -p /tmp 'my param 1'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | TacB0sS |
| Solution 3 | |
| Solution 4 |

