前些天写了一篇《标准输出的重定向》,这几天又遇到了读取配置文件的任务,想一改原来的" FILE* fp ……"之类的写法,换用一种新的灵活性更高的方式,即把标准输出重定向到一个管道的写端,再从管道的读端获取内容。
首先我们有这样一个函数,用来获取system调用的输出:
static int getResultFromSystemCall(const char* pCmd, char* pResult, int size) { int fd[2]; if(pipe(fd)) { printf("pipe error!\n"); return -1; } //hide stdout int bak_fd = dup(STDOUT_FILENO); int new_fd = dup2(fd[1], STDOUT_FILENO); //the output of `pCmd` writes into fd[1] system(pCmd); read(fd[0], pResult, size-1); pResult[strlen(pResult)-1] = 0; //resume stdout dup2(bak_fd, new_fd); return 0; }
这样,我们可以通过下面的形式调用它:
char cmd[100] = {0}; getResultFromSystemCall("export aaa=1234 && echo ${aaa#=}", res, sizeof(res)/sizeof(res[0]));
我们可以获得 1234 这个值了。
我们把该函数的第一个参数再弄的复杂一点,如
cat test.conf | grep -m 1 -E "^aaa" | cut -d= -f2 | sed 's/[[:space:]]*//g'
下面解释一下,各牛们请飘过:
#aaa is test key aaa = 1234 aaa = bbbb
test.conf 内容如上。
第一层管道的grep,-m 1 指定了我们只获取符合条件的第一行, -E 指定使用grep的扩展形式,也可以用 egrep 代替 grep
-E , "^aaa" 指定了以aaa开头行的条件,用来回避#开头的注释行。
第二层管道的cut,用来截取以 = 分割的第2个域。
第三层管道的sed,用来将 1234 前面的各种tab和空格去掉。
tools.c 的代码请见 http://www.oschina.net/code/snippet_616273_14056
我们可以把其中的main函数稍稍改装一下,如
int readValueFromConf(const char* filePath, const char* key, char* res, int size) { char cmd[100] = {0}; sprintf(cmd, "cat %s | grep -m 1 -E \"^%s\" | cut -d= -f2 | sed 's/[[:space:]]*//g'", filePath, key); return getResultFromSystemCall(cmd, res, size); }
这样,我们就完成了C语言读取配置文件的另类写法。
时间: 2024-10-28 07:30:42