文本处理的难点
有一个文本文件,内容如下,摘抄其中两行内容如下,里面有两个配置db_addr, local_ip这两个配置,需要在不同环境要修改的。
db_addr=1.2.3.4:3306
local_ip=192.168.2.4
但是哪些地方要修改呢?为了提醒后续的维护者,我们给要修改的地方加个备注吧。
db_addr=1.2.3.4:3306 # 这里要修改
local_ip=192.168.2.4 # 这里要修改
....
...
if len(a) = 1024 { # 这里要修改1024
...
}
...
用sed替换?
让别人一个一个地方去修改,也太麻烦了,有没有可能用脚本去处理呢?例如我们用DB_ADDR和LOCAL_IP这种字符串作为占位符,然后我们就可以用sed之类的命令去做替换了。
db_addr=DB_ADDR
local_ip=LOCAL_IP
sed -i 's/DB_ADDR/1.2.3.4:3306/g;s/LOCAL_IP/192.168.0.1/g' 1.cfg
这样做是有点方便了,但是也有以下几个问题
- 如果定义的占位符太多,sed会变得越来越长
- 如果某些占位符里本身就含有/或者一些特殊含义的字符,就需要做特殊处理了
用M4吧,专业的人做专业的事情
apt-get install m4
通过命令行定义宏
1.m4
db_addr=DB_ADDR
local_ip=LOCAL_IP
....
...
if len(a) = MAX_LEN {
...
}
...
M4可以使用-D来定义宏和宏对应的值,默认输出到标准输出,我们可以用>将输出写到文件中
m4 -D DB_ADDR=1.2.3.4:3306 -D LOCAL_IP=192.168.2.2 -D MAX_LEN=2048 1.m4
db_addr=1.2.3.4:3306
local_ip=192.168.2.2
....
...
if 1 = 2048 {
...
}
...
用define语句定义宏
- 用define()语句来定义宏
- 用`‘来作为字符串引用,避免被展开
define(`DB_ADDR', `1.2.3.4:3306')
define(`LOCAL_IP', `192.168.2.2')
define(`MAX_LEN', `2048')
db_addr=DB_ADDR
local_ip=LOCAL_IP
....
...
if len(a) = MAX_LEN {
...
}
...
执行命令m4 1.m4
, 可以看到宏展开,但是有很多空行。
db_addr=1.2.3.4:3306
local_ip=192.168.2.2
....
...
if 1 = 2048 {
...
}
...%
用dnl避免产生空行
在define语句的末尾,加上dnl
define(`DB_ADDR', `1.2.3.4:3306')dnl
define(`LOCAL_IP', `192.168.2.2')dnl
define(`MAX_LEN', `2048')dnl
db_addr=DB_ADDR
local_ip=LOCAL_IP
....
...
if len(a) = MAX_LEN {
...
}
...
执行m4 1.m4
可以看到,空行没了
db_addr=1.2.3.4:3306
local_ip=192.168.2.2
....
...
if 1 = 2048 {
...
}
...
抽离出宏配置文件
将1.m4分成两个文件1.m4, 1.conf
1.conf
divert(-1)
define(`DB_ADDR', `1.2.3.4:3306')
define(`LOCAL_IP', `192.168.2.2')
define(`MAX_LEN', `2048')
divert(0)
1.m4
db_addr=DB_ADDR
local_ip=LOCAL_IP
....
...
if len(a) = MAX_LEN {
...
}
...
执行:m4 1.conf 1.m4
db_addr=1.2.3.4:3306
local_ip=192.168.2.2
....
...
if 1 = 2048 {
...
}
...
读取环境变量
define(`MY_NAME', `esyscmd(`printf "${MY_NAME:-wdd}"')')dnl