惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园 - Franky
罗磊的独立博客
G
Google Developers Blog
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
V
V2EX
F
Fortinet All Blogs
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
U
Unit 42
GbyAI
GbyAI
A
About on SuperTechFans
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
Martin Fowler
Martin Fowler
D
DataBreaches.Net
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog

f2h2h1's blog

使用yii3实现一个微框架 claw养殖技术 计算机网络基础知识 定时任务 ACME的使用经验 magento2加上varnish缓存 开发Magento2的模块 在magento2中使用persisted-query socket编程 一些开发笔记 一段CSDN文章主要内容的油猴脚本 电子邮件的不完整总结 git的笔记 在Windows下配置PHP服务器 终端,控制台和外壳 PHP各种运行方式的不完整总结 把网页导出成PDF 和颜色相关的笔记 HTTP认证方式的不完整总结 SEO的经验 密码学入门简明指南 文件的上传和下载 用纯CSS3实现的滑动按钮 在VSCode里调试PHP Linux的GUI 关于字符编码的一些坑 nc的使用和原理 在Windows下安装Magento2 对JS原型链的理解 使用docker-compose部署magento2
使用shell实现的kv数据库
2023-03-20 · via f2h2h1's blog

这篇文章最后更新的时间在六个月之前,文章所叙述的内容可能已经失效,请谨慎参考!

写这份脚本的灵感来自这本书《设计数据密集型应用》 https://github.com/Vonng/ddia

在这本书的第三章里提及了一个使用 shell 实现的数据库

#!/bin/bash
db_set () {
  echo "$1,$2" >> database
}
db_get () {
  grep "^$1," database | sed -e "s/^$1,//" | tail -n 1
}

笔者在这段小脚本的基础上进行了一些拓展。新增了一些功能,例如 del show 之类的。

这份脚本依赖这几个程序,可以使用类似这样的命令 ./shdb.sh test 来判断当前环境是否有这些程序

  • bash
  • grep
  • sed
  • awk
  • cat
  • tac
  • tail
  • cut
  • tr

可以使用类似这样的命令 ./shdb.sh help 来输出使用帮助

这份脚本可以在 git for windows 的 git bash 里运行

源码

#!/bin/bash

SHELL_FOLDER=""

if [ -z "$SHELL_FOLDER" ]; then
    SHELL_FOLDER=$(dirname $(readlink -f "$0"))
fi

DB_PATH="$SHELL_FOLDER/$2.csv"

version() {
    echo "0.0.1"
}
help() {
    echo "version: "$(version)
    echo "folder: "$SHELL_FOLDER
    echo ""
    cat << EOF
Usage:
    command [arguments]

Command:
    version     
    help        
    test        test dependence
    create      create table
                example: ./dbsh.sh create default
    remove      remove table
                example: ./dbsh.sh remove default
    list        show all table
                example: ./dbsh.sh list
    rename      rename table
                example: ./dbsh.sh rename old_name new_name
    reindex     rebuild index
                example: ./dbsh.sh reindex default
    set         set a value by key
                example: ./dbsh.sh set default key1 value
    get         get a value by key
                example: ./dbsh.sh get default key1
    del         delete a value by key
                example: ./dbsh.sh del default key1
    truncate    truncate table
                example: ./dbsh.sh truncate default
    show        show all data for a table
                example: ./dbsh.sh show default
    rawshow     show all data for a table with out format
                example: ./dbsh.sh rawshow default

Note:
    file is saved in CSV format.
    set can overwrite old data.
    modify this variable SHELL_FOLDER to change the directory.
    key is a keyword, you can not use it.
EOF
}
db_create() {
    if [ ! -f "$1" ]; then
        echo "key,value" >> $1
    else
        echo "$1 already exists"
        return 1
    fi
}
db_remove() {
    if [ -f "$1" ]; then
        rm $1
    fi
}
db_list() {
    ls $(echo $SHELL_FOLDER'/*.csv')
}
db_rename() {
    old=$SHELL_FOLDER'/'$1'.csv'
    new=$SHELL_FOLDER'/'$2'.csv'
    if [ ! -f "$old" ]; then
        echo "$old  does not exist"
        return 1
    fi
    if [ -f "$new" ]; then
        echo "$new already exists"
        return 1
    fi
    mv $old $new
}
db_reindex() {
    if [ ! -f "$1" ]; then
        echo "$1 does not exist"
        return 1
    fi
    sed -i '/^[  \t]*$/d' $1
    tac $1 | awk -F, '!a[$1]++{print}' | tac > $1
}
db_set() {
    if [ $2 == "key" ]; then
        echo "set fail, key is keyword"
        return 1
    fi
    if [ -f "$1" ]; then
        echo "$2,$3" >> $1
    fi
}
db_get() {
    if [ -f "$1" ]; then
        grep "^$2," $1 | sed -e "s/^$2,//" | tail -n 1
    fi
}
db_del() {
    if [ -f "$1" ]; then
        sed -i $(grep -n "^$2," $1 | cut -d  ":" -f 1 | sed -e "s/$/d/g" | tr "\n" ";")'' $1
    fi
}
db_truncate() {
    sed -i '2,$d' $1
}
db_show() {
    if [ ! -f "$1" ]; then
        echo "$1 does not exist"
        return 1
    fi
    tac $1 | awk -F, '!a[$1]++{print}' | tac | cat -n
}
db_rawshow() {
    if [ ! -f "$1" ]; then
        echo "$1 does not exist"
        return 1
    fi
    cat $1
}
db_test() {
    test_dependence() {
        type $1 > /dev/null 2>&1
        if [ ! $? -eq 0 ]; then
            echo "no $1"
            echo "test fail"
            exit 1
        fi
        echo "    $1 ok"
    }
    echo "SHELL_FOLDER is $SHELL_FOLDER"
    if [ ! -d $SHELL_FOLDER ]; then
        echo "SHELL_FOLDER is not existent"
        exit 1
    else
        echo "SHELL_FOLDER is existent"
    fi
    if [ ! -r $SHELL_FOLDER ]; then
        echo "SHELL_FOLDER can not read"
        exit 1
    else
        echo "SHELL_FOLDER can read"
    fi
    if [ ! -w $SHELL_FOLDER ]; then
        echo "SHELL_FOLDER can not write"
        exit 1
    else
        echo "SHELL_FOLDER can write"
    fi
    echo "test dependence"
    test_dependence sh
    test_dependence grep
    test_dependence sed
    test_dependence awk
    test_dependence cat
    test_dependence tac
    test_dependence tail
    test_dependence cut
    test_dependence tr
    echo "passed the test"
}
case $1 in
    "h"|"help")
        help
    ;;
    "v"|"version")
        version
    ;;
    "create")
        db_create $DB_PATH
    ;;
    "remove")
        db_remove $DB_PATH
    ;;
    "list")
        db_list
    ;;
    "rename")
        db_rename $2 $3
    ;;
    "reindex")
        db_reindex $DB_PATH
    ;;
    "set")
        db_set $DB_PATH $3 $4
    ;;
    "get")
        db_get $DB_PATH $3
    ;;
    "del")
        db_del $DB_PATH $3
    ;;
    "truncate")
        db_truncate $DB_PATH
    ;;
    "show")
        db_show $DB_PATH
    ;;
    "rawshow")
        db_rawshow $DB_PATH
    ;;
    "test")
        db_test
    ;;
    *)
        help
    ;;
esac
EXIT_CODE=$?
if [ ! $EXIT_CODE -eq 0 ]; then
    exit $EXIT_CODE
fi
exit 0