bash map

我自己对 bash 的编程是有很多槽点的. 比如函数只能返回整数值, 取函数返回值只能用 $?. 对不加双引号的变化会以空白符分割, 导致隐藏的很深的 bug. 数值型 for 里边的变量是全局的. 为了从一个函数中取得返回值必须得用全局变量等等不一而足. 难怪大部分的 bash 文件都很小, 就是它可能应付不了稍微中型的项目的复杂度. bash 中基本没有什么解耦和模块性可言. 我自己写的 bash 来来去去加起来可能不超过 3000 行. 所以其实用起来也不是很顺手.

好了, 吐槽过了. 讲一下花了半个下午和一个晚上在 bash 中实现的 map. 如果 bash 的版本在 4.0 以上是可以直接使用关联数组的. 不可谓是一个进步. 但是我怀疑这个关联数组的值应该不能是另外一个关联数组而必须是字符串. 现在我的机器用的是 3.x, 也是想尝试一下自己实现 map, 所以我做在 bash 中做了一个 map: map.sh. 其实这个想法由来已久, 之前在服务器上写脚本的时候就常感慨, 要是 bash 中有 map 的话, 那么存取都方便很多了. 比如之前做过的一个清理数据库功能, 数据表中记录是根据其中一个时间字段来判断是不是要删除. 但是每个数据库表的对应字段名其实是不一样的. 当时使用了相邻两个数组元素表示.

当第一次向字典中放入数据时, 需要以 MRLONG_MAP_GLOBAL_MAP 的值为第一个参数, 其后跟键和值去调用 mrlong_map_set 函数, 此时会给变量 MRLONG_MAP_NEXT_MAP 设置下一级的字典, 这样便可以拥有多级字典了. 这里有一个跟我们平常用到的字典不一样的地方, 就是给字典里的一个键设置了一个值以后还能够以这个键作为下一级的字典, 而已经设置的值并不会消失. 通过 mrlong_map_get 函数, 你可以获得某个键的值保存在 MRLONG_MAP_CURRENT_VALUE, 同时可以获得这个键作为下一级的字典. 假如这个键之前是没有设置过的, 那么不好意思, MRLONG_MAP_NEXT_MAP 和 MRLONG_MAP_CURRENT_MAP 将会被设置为空字符串. 调用 mrlong_map_keys 并以 MRLONG_MAP_GLOBAL_MAP 或者 MRLONG_MAP_NEXT_MAP 作为唯一参数的话, 可以获取当前字典中的所有键保存在全局变量 MRLONG_MAP_CURRENT_KEYS .

在 map.sh 的最下边有一些示范. 整个 map 的实现用到了大量自动生成的以 __mrlong_map 开头的全局变量, 每个用过的键都会保存在 MRLONG_MAP_GLOBAL_KEYS 数组中. 而所有的值都保存在以键在 MRLONG_MAP_GLOBAL_KEYS 中的索引的某种形式的变量中. 比如在 MRLONG_MAP_GLOBAL_MAP 中设置了一个键 key 值为 value. 那么这个值会以 __mrlong_map_0=value 方式保存. key 将会放在 MRLONG_MAP_GLOBAL_KEYS 的第一个元素处. 二级、三级、多级都是类似的.

Leave a Reply

Your email address will not be published. Required fields are marked *