1.本文针对的文本文件格式类型是形如 linux系统标准服务配置文件的文本格式。比如dhcpd.conf中的
# option definitions common to all supported networks...
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
对于形如windows标准配置文件格式的文件,比如
[optionName]
option1=item1;
option2=item2;
不做考虑。
2. linux文件操作的常规方法:
a。c语言解析。逐行获取逐行分析,开发效率比较低。
b。c语言+脚本语言。脚本语言包括lua,perl,shell,Ruby等。
经过比较,推荐shell或者lua。因为都是c语言开发的脚本语言,与c语言的结合相对比较好。
shell是unix posix的一部分,出现的时间早,因此资源相对丰富。可读性可维护性比shell差。
lua 可读性比shell好很多。不过考虑到资源丰富的问题,选择了shell。
3 shell + c 读取配置文件信息。
shell的基本教材推荐 http://see.xidian.edu.cn/cpp/view/6994.html。
放个例子上来,读取dhcpd.conf中的一个字段数据。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
static int my_system(const char* pCmd, char* pResult, int size,int* pOutLen);
int main(void)
{
char result[1025];
int iOutLen = 0;
my_system("cat dhcpd.conf | awk '/^option[[:blank:]]+/ {print $3}'", result, 1025,&iOutLen);
if (strlen(result) == iOutLen)
printf("the result is: %s \r\n", result);
else
{
int iTemp = 0;
while(iOutLen)
{
iTemp += strlen(result+iTemp);
printf("the result is :%s \r\n",result);
iOutLen = iOutLen - iTemp;
}
}
iOutLen = 0;
my_system("sed -n '/^option/p' dhcpd.conf",result,1025,&iOutLen);
if (strlen(result) == iOutLen)
printf("the result is: %s \r\n", result);
else
{
int iTemp = 0;
while(iOutLen)
{
iTemp += strlen(result+iTemp);
printf("the result is :%s \r\n",result);
iOutLen = iOutLen - iTemp;
}
}
return 0;
}
static int my_system(const char* pCmd, char* pResult, int size,int* pOutLen)
{
int fd[2];
int pid;
int count;
int left;
char* p = 0;
int maxlen = size-1;
memset(pResult, 0, size);
if(pipe(fd)) //创建管道
{
return -1;
}
if((pid = fork()) == 0) //创建子进程
{// chile process
int fd2[2];
if(pipe(fd2)) //创建管道2
{
return -1;
}
close(1); //关闭系统标准输出1,即屏幕输出
dup2(fd2[1],1); //将系统标准输出1重定向到文件描述fd2[1]中,fd2[1]是管道fd2的写入端。
close(fd[0]);//关闭管道1的读入端
close(fd2[1]);//关闭管道2的写入端
system(pCmd);//执行命令
read(fd2[0], pResult, maxlen); //从管道2中读取执行结果
pResult[strlen(pResult)-1] = 0;
write(fd[1], pResult, strlen(pResult)); //将执行结果pResult写入管道fd
close(fd2[0]);//关闭管道fd2的读入端;
exit(0);//子进程退出
}
// parent process
close(fd[1]);
p = pResult;
left = maxlen;
while((count = read(fd[0], p, left))) {
p += count;
left -= count;
(*pOutLen) += count;//add by wangxya
if(left == 0)
break;
}
close(fd[0]);
return 0;
}
执行结果为:
the result is: "example.org";
ns1.example.org,
the result is: option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
可以看到,awk擅长处理列数据;sed擅长处理行数据。
4.直接读取配置文件全部内容,且去掉注释行的方法:
my_system("sed '/^ *#/d' dhcpd.conf",result,1025,&iOutLen);
执行结果
the result is:
ddns-update-style none;
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
5.直接读取配置文件全部内容,并去掉注释和空白行的方法
my_system("sed -n '/^\s*[^# \t].*$/p' dhcpd.conf",result,1025,&iOutLen);
the result is: ddns-update-style none;
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
6.获取指定配置文件中第一行的第三列的且为option+空格开头的参数
my_system("sed -n '/^\s*[^# \t].*$/p' dhcpd.conf | awk '/^option[[:blank:]]+/ {print $3}'| sed -n '1p'",result,1025,&iOutLen);
执行结果
the result is: option param 3 itemp 1 is "example.org";
7.修改配置文件中的内容
命令行结果
sed -i '/option/{/domain-name-servers/s/ns2.example.org/iwn.com.org/g}' dhcpd.conf
将记录
option domain-name-servers ns1.example.org, ns2.example.org;
修改为
option domain-name-servers ns1.example.org, iwn.com.org;
8.比较文件差异,并获取差异部分的命令:
原文连接:http://blog.xuyuan.me/2011/03/17/unix_diff.html
命令: diff temp1.txt temp2.txt | grep ">" | sed 's/> //g'
comm -13 temp1.txt temp2.txt
comm命令用来比较两个文件,具体用法:
comm [-123] file1 file2
-1 过滤file1独有的内容
-2 过滤file2独有的内容
-3 过滤file1和file2重复的内容
9.获取dhcpd.conf文件除掉注释和空白行以外的行数:
sed -n '/^\\s*[^#].*$/p' dhcpd.conf | sed '/^[[:space:]][[:space:]]*$/d' | sed -n '$='