blob: 99180b31154c1d7a5e693599317903fa05f501be (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
---
title: "An Embedded Key/Value Store for Shell Scripts"
date: 2012-10-07T10:06:00Z
comments: true
tags: ['shell scripting', 'databases']
---
UPDATE: this is now available as a [sub](http://github.com/37signals/sub) command, here: [kiev](http://github.com/capotej/kiev)
Cooked this up last night when I needed a simple key/value store for use in a shell script:
<!--more-->
```sh db.sh
#!/bin/sh
DBFILE=example.db
put(){
echo "export kv_$1=$2" >> $DBFILE
}
del(){
echo "unset kv_$1" >> $DBFILE
}
get(){
source $DBFILE
eval r=\$$(echo "kv_$1")
echo $r
}
list(){
source $DBFILE
for i in $(env | grep "kv_" | cut -d= -f1 ); do
eval r=\$$i; echo $(echo $i | sed -e 's/kv_//') $r;
done
}
## cmd dispatch
if [ ${1:-0} == "set" ]; then
put $2 $3
elif [ ${1:-0} == "get" ] ; then
get $2
elif [ ${1:-0} == "list" ] ; then
list
elif [ ${1:-0} == "del" ] ; then
del $2
else
echo "unknown cmd"
fi
```
Use it like so:
`$ ./db.sh set foo bar`
`$ ./db.sh get foo`
`$ ./db.sh set foo baz`
`$ ./db.sh get foo`
`$ ./db.sh del foo`
`$ ./db.sh list`
## How it works
Every time you update/set/delete a value, it writes a shell expression to an append-only log,
exporting a shell variable (key) with that value. By sourcing the file every time we read a value, we
replay the log, bringing our environment to a consistent state. Then, reading the value is just looking
up that dynamic variable (key) in our shell environment.
|