阅读302 返回首页    go 阿里云 go 技术社区[云栖]


C语言读取配置文件的另类写法

前些天写了一篇《标准输出的重定向》,这几天又遇到了读取配置文件的任务,想一改原来的" 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 的代码请见 https://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语言读取配置文件的另类写法。

最后更新:2017-04-02 15:14:54

  上一篇:go 茵茵的第一课
  下一篇:go 16进制的简单运算