最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Linux環(huán)境自用文本數(shù)據(jù)庫Camelia山茶花實現(xiàn)介紹

2022-08-20 01:47 作者:纖凌依  | 我要投稿

github鏈接:https://github.com/raine01/databaseCamelia

說它是數(shù)據(jù)庫有些抬舉它了。山茶花只是一個shell腳本,把一些信息存儲進文本文件。類似的項目網(wǎng)上可能一搜一把,但想著好不容易寫出來了別浪費掉,就放上來了~萬一有人喜歡呢

起因是我的低配云服務(wù)器需要存儲點東西,為了這不到十萬行的東西裝個數(shù)據(jù)庫有點沒必要。想起前幾天親友用csv存東西,感覺自己也可以參考著做一個

由于時間長了自己都會混淆,所以先來明確些概念

:由于有些數(shù)據(jù)希望保留每一次變更記錄(這些key對應(yīng)的value不常修改),另一些只需要保留最新的狀態(tài)(這些key對應(yīng)的value經(jīng)常修改),或者同一個key希望保留多份不同的value。因此我引入了這個概念。每個山茶花生成的具有不同前綴的記錄數(shù)據(jù)的文件稱為一個

版本:由于山茶花的修改與刪除不是真正意義上的修改刪除,只是放了特殊標(biāo)識用以區(qū)分的插入操作,因此變動的越頻繁就越容易產(chǎn)生廢數(shù)據(jù)。我的應(yīng)對策略是隔一段時間手動執(zhí)行一次tar操作,把每個key的最新版本copy進一個新的文件,最后執(zhí)行del操作的數(shù)據(jù)則不考慮(似乎大家都是類似的做法)。同一個每次壓縮后生成的文件我稱為一個版本

選項-u-d,-hv都是山茶花的選項

原始庫名:庫可以被多次壓縮,最初的未被壓縮的庫名(不帶有下劃線與數(shù)字)被稱為原始庫名

版本庫名原始庫名_版本號,且該版本是數(shù)次壓縮后的最新版本,被我稱為版本庫名

下面是data某個版本的一段(可以把它當(dāng)成全部),存儲數(shù)據(jù)的結(jié)構(gòu)大概像這樣:

第一行以#開頭,之后是這個版本的創(chuàng)建時間(2022年1月3日18:19:48),版本名(原始庫名或原始庫名后跟著下劃線與數(shù)字),以及創(chuàng)建這個庫的用戶。除了留痕以外還可以用于校驗(后文會提到)

下面每一行都是相同的結(jié)構(gòu):key,option(i表示插入/更新,d表示刪除),value,操作時間

注釋中的這一行本身是一個示例,其中Camelia是這個可執(zhí)行文件自身。

我通常喜歡跳轉(zhuǎn)至山茶花所在的目錄,使用

chmod 777 Camelia

賦權(quán)。然后使用類似這樣的命令(加上./意味著執(zhí)行)

./Camelia testdb -i key1 value1 -i key2 value2 -i key1 Meow key1 key2

如果你像我一樣不熟悉shell,那么你也可以像我一樣使用這些命令

粗略解釋下:

testdb原始庫名

-i key1 value1插入一條數(shù)據(jù),key是key1,value是value1

-i key2 value2與上面類似

-i key1 Meow與前面兩個的操作相同,不過就結(jié)果而言這個是更新操作,將key1對應(yīng)的value修改為了Meow

key1打印key1的值

key2打印key2的值

跳過前面的一堆注釋和函數(shù),我們先來看看后面的部分:

一個變量tname

一個變量Cameliatime,值為特定格式的當(dāng)前時間,如220204014719(22年02月4日1點47分19秒)

執(zhí)行腳本中名為help_tname的函數(shù),函數(shù)的參數(shù)是上方示例中的第一個參數(shù),即testdb這個詞

shift,一個對于參數(shù)來說的出棧操作,原本的第一個參數(shù)沒了(但是沒關(guān)系,它已經(jīng)完成它的任務(wù)了),第二個變第一個,第三個變第二個,以此類推

while [ -n "$1" ]把參數(shù)1變成字符串,如果這個字符串不為null,長度大于0,那么執(zhí)行下面的部分

do表示這個while函數(shù)體開始,done表示這個while函數(shù)體結(jié)束

case $1 in匹配第一個參數(shù)(上方的示例中是-i,testdb已經(jīng)被shift掉了),看看是下面這些中的哪一個

-u|-i) ins_del $2,i,$3,$Cameliatime如果是-u或者-i,執(zhí)行ins_del這個函數(shù),參數(shù)是三個變量和其余部分拼接起來的字符串(第一次循環(huán)中拼接起來的字符串是key1,i,value1,220204014719

;;兩個分號表示跳出case...esac代碼塊

后面的幾行大同小異。特別說一下*)表示匹配任意的選項。if [[ $1 == -* ]]如果這個選項是以短橫線開頭,那么提示異常信息然后退出,狀態(tài)碼不是通常的0而是1。不以短橫線開頭就執(zhí)行sel函數(shù),并且把選項本身作為參數(shù)。也就是說,不加短橫線的選項其實就是查詢key為該選項的value的值

這幾行代碼的縮進很糟糕,可能是因為我當(dāng)時調(diào)整了vim關(guān)于tab的設(shè)置。我不打算修改

按上方的出場順序介紹各個函數(shù)中的一些知識點

help_tname()

????$#:參數(shù)的個數(shù),這個條件語句的意思是表示如果沒有選項或者第一個選項為--help,那么awk -F'### ' '/^###/ { print $2 }' "$0"會篩選###開頭的行,并用'### '分割這些行(山茶花開頭的那些注釋行),打印這些行用'### '分割后的第二部分。那么這個awk命令讀取的是哪個文件呢?沒有默認(rèn)自己讀自己這種設(shè)定,awk讀取的文件是$0這個參數(shù)的值,也就是文件本身的文件名

????往下,是另一個邏輯判斷。參考下方開頭看過的示例,這里應(yīng)該是一個原始庫名。所以會有"Honey,don't call a table $1"的提示

接下來,山茶花需要確定一下版本庫名

tname=$(ls|egrep "^$1(_[1-9]\d*)?$"|tail -1)ls展示當(dāng)前目錄所有的文件、管道傳給egrep命令(grep命令的變體,同grep -e,意為使用正則搜索)篩選。這個文件以$1開頭(在示例中為testdb)、后面可能跟著下劃線和若干非0開頭的數(shù)字并以之結(jié)尾。管道將篩選出的一大串文件名傳遞給tail命令,并留下最后一個作為版本庫名

我來舉個例子:我在放著很多我破爛的路徑下創(chuàng)建了一個,名為db。并在之后使用-tar選項壓縮了五次。

現(xiàn)在目錄下有如下文件

egrep之后剩下了這些

tail -1之后剩下的是

這個就是版本庫名了~

if [[ -z $tname ]]; then,如果版本庫名為空(說白了就是庫還沒建立)

那么新建一個,并寫入留痕信息"#$Cameliatime|$1|${USER}"并重新給代表庫名的變量賦值

這三個$符開頭的都是變量(前面也提到過),分別是當(dāng)前時間、版本庫名、當(dāng)前用戶。這三個變量以及豎線拼接成一個字符串,構(gòu)成了每個版本的第一行

與上方if相對的,如果版本庫名不為空,那么進行校驗:

local tnamesign=$(head -n 1 $tname|cut -d "|" -f 2)

local用于定義局部變量,作用域為函數(shù)內(nèi)部

head命令顯示文件的開頭部分,這里顯示的是名為$name這個變量的文件的第一行

cut用于截取,-d用于指定分隔符,-f表示選取分隔后的第幾個(常和-d連用)

這行命令的意思是截取版本庫名(假設(shè)它是版本庫名)這個文件的第一行,并且取出第一行用豎線分隔后的第二部分,這個第二部分對于山茶花的任意一個版本來說就是這個文件的文件名。這個校驗對于總寫錯原始庫名的我來說格外有用

最后我們校驗一下,如果文件第一行豎線隔開的第二個字符串和你的原始庫名不同,那么它就不是山茶花某個庫的某個版本。我們打印提示信息,然后返回-1

現(xiàn)在山茶花確定版本庫名了,存儲這個版本庫名的變量整個shell腳本內(nèi)均可以使用

ins_del()

幾個字符串拼接起來,然后追加到版本庫名的最后一行。>表示替換,>>表示追加

sel()

taccat剛好相反,也就是倒著找。我們找這個文件以相應(yīng)key開頭的第一行,并且用i來過濾(如前文所說,i表示插入/更新,d表示刪除。如果找到的最新一行是d開頭的,那么表示該key對應(yīng)的value已經(jīng)被邏輯刪除了,邏輯刪除時我們返回空)

selhistory()

傳入的參數(shù)是key-value數(shù)據(jù)的key值,我們使用grep搜索版本庫名這個文件,查找以key開頭的行,并附上一個逗號以免某個key值是另一個key值的開頭。我們將搜索出來的行用逗號分隔并取出第2、3、4個參數(shù)

使用./Camelia data -h card命令后會顯示

表示在這些時間執(zhí)行的都是插入(更新)操作

selhisval()

與上方相同,但是只顯示第三列

./Camelia data -hv card的結(jié)果如上

selhiscount()

與上面一樣,但是多了一個分類計數(shù)功能。我們來粗略地看一下這個awk命令:

經(jīng)過前面的處理后獲取的東西會被awk視為一行

NF表示列數(shù)(默認(rèn)空格分隔)

$i表示這一列的內(nèi)容

END后面跟的是處理完所有行后執(zhí)行的操作,我們在END前后用兩個大括號把每行需要執(zhí)行的操作和全部處理完后進行的操作包起來

先來看每行都需要執(zhí)行的操作for(i=1;i<=NF;i++)a[$i]++。遍歷每一列,并且把角標(biāo)為這列內(nèi)容的項的值加一,例如

處理完后大概像是這樣:

再來看后半截for(x in a)print x,a[x],這次是遍歷剛剛創(chuàng)建的數(shù)組,逐項打印他們的角標(biāo)(索引),后面跟著該項的值(在這里就是他們出現(xiàn)過的次數(shù))

./Camelia data -hc card的結(jié)果如上(是的,awk中輸入逗號,打印出來的是空格),如果你想統(tǒng)計你游戲職業(yè)各種卡牌出現(xiàn)的頻率、某個客人光顧你店的次數(shù)等,這會是個很實用的功能

tar()

為了避免你的隨著不斷的使用效率下降的過于離譜,山茶花加入了壓縮功能。邏輯上來說就是對于相同的key只保留最新的一行

我們粗略看看它是怎么工作的:

暫存當(dāng)前的版本庫名

%分隔tname這個變量,獲取前半部分

#獲取后半部分

(如果用db_5舉例子,前半部分就是db,后半部分就是5)

index加一(5變成6)

更新儲存版本庫名的變量,然后把校驗信息寫入

tail命令篩選版本庫名文件第二行至末尾的部分(第一行是校驗信息不處理),并交給awk處理

awk命令創(chuàng)建一個數(shù)組a,將每行內(nèi)容賦值給數(shù)組中角標(biāo)為key的項(數(shù)組內(nèi)容不能重復(fù),這里相當(dāng)于一個去重操作),然后再把每一行追加進新的版本庫名文件中

(這里的tail不能替換為tac,因為awk是逐行處理的,而我們的思路是用新的頂?shù)襞f的。如果用tac命令,我們將會保留最舊的數(shù)據(jù))

直接退出,不給你繼續(xù)操作的機會。我忘了我為什么直接退出了,可能是不推崇頻繁的壓縮操作?

本人linux相關(guān)的知識其實蠻匱乏的,還望共同討論不吝賜教,比心~?

下面放上完整的腳本




Linux環(huán)境自用文本數(shù)據(jù)庫Camelia山茶花實現(xiàn)介紹的評論 (共 條)

分享到微博請遵守國家法律
托克逊县| 贵定县| 饶河县| 汾阳市| 舒兰市| 咸宁市| 怀安县| 灵璧县| 和田县| 铜川市| 年辖:市辖区| 玉环县| 平阴县| 蒙自县| 黑山县| 青浦区| 蕲春县| 乌恰县| 凉城县| 五大连池市| 固阳县| 赤壁市| 榆中县| 宁南县| 江都市| 晋江市| 泗水县| 彭州市| 宜城市| 元谋县| 龙陵县| 汝阳县| 贵阳市| 安乡县| 浏阳市| 教育| 昌平区| 新邵县| 布尔津县| 册亨县| 内黄县|