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

推荐订阅源

Scott Helme
Scott Helme
N
Netflix TechBlog - Medium
AI
AI
Security Latest
Security Latest
GbyAI
GbyAI
P
Proofpoint News Feed
Y
Y Combinator Blog
A
Arctic Wolf
G
Google Developers Blog
U
Unit 42
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Vulnerabilities – Threatpost
Know Your Adversary
Know Your Adversary
Cisco Talos Blog
Cisco Talos Blog
T
Tor Project blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
L
Lohrmann on Cybersecurity
C
CERT Recently Published Vulnerability Notes
C
Check Point Blog
B
Blog RSS Feed
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cisco Blogs
云风的 BLOG
云风的 BLOG
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Security Blog
Microsoft Security Blog
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
Latest news
Latest news
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
WordPress大学
WordPress大学
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
The Hacker News
The Hacker News
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
Project Zero
Project Zero
博客园_首页

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 浏览器和服务器通讯方式的不完整总结 观察网站性能 一些关于Linux的笔记 telnet的不完整总结 在Windows下安装pear MySQL的时间类型和时间相关的函数 Windows下通过PEB读取进程的环境变量 关于 在VSCode里使用Xdebug远程调试PHP 在Windows下搭建git服务 关于环境变量的不完整总结 如何完成以xx管理系统为选题的毕业设计 数字号码资源 各种标记语言 使用PowerShell实现的http服务器 kind相关经验 DNSSEC简介 nginx+ffmpeg+websocket实现的直播例子 使用Tesseract识别字符验证码 使用docker部署nuxt FirstData后台的设置 paypal,firtdata,支付宝的不完整接入指南 微信支付的不完整接入指南 用docker-compose部署lnmp环境 mongodb分片 练习
使用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