您的位置:首页 > 运维架构 > Shell

Shell实现(三)读取命令的实现

2015-10-24 22:37 471 查看

基本思路

读取命令我采取的读取整个字符串后再进行分段和分析:

首先是parse_token将字符串通过分号为分隔,得到每组命令,每组命令当中只包含管道,输入输出重定向和单条命令及其参数。

然后是parse_group将每段得到的字符串通过管道为分隔,得到只包含参数,输入输出重定向和单条命令的更加简单的命令串

最后是parse_command分析单条指令,得到输入输出重定向的文件流和命令的属性还有命令的参数。

从内存中取出占位放入命令,然后将命令分组(组内连续)

具体实现:

首先是parse_token

//遍历字符串以";"为分隔得到字符串组,用0取代;代表字符串结束,实现字符串的划分
void parse_token ( char* buf )
{
int n = strlen ( buf ),i,j=0;
n--;
buf
= 0;
for ( i = 0 ; i < n ; i++ )
if ( buf[i] == ';'|| i == n-1 )
{
if ( buf[i] == ';' )
buf[i] = 0;
parse_group ( buf+j );
j = i+1;
}
}


然后是parse_group,与parse_token思路相似

//以“|”为分隔得到字符串组,用0取代|的位置代表字符串结束,实现字符串的划分
//mode代表得到的单条指令在组中的位置,只有两端的不通过管道的传递信息
//1代表中间位置
void parse_group ( char* buf )
{
int n = strlen ( buf ),i,j=0;
int x = cnt_cmd;
for ( i = 0 ; i < n ; i++ )
if ( buf[i] == '|' || i == n-1 )
{
int mode = 0;
if ( buf[i] == '|' )
{
buf[i] = 0;
mode = 1;
}
parse_command ( buf+j , mode );
j = i+1;
}
group[cnt_group].first = x;//对指令进行分组
group[cnt_group].last = cnt_cmd;
cnt_group++;
}


最后是parse_command

//parse_command分析单条指令
void parse_command ( char* buf , int mode )
{
int n = strlen ( buf ),i=0,j=0;
while ( buf[i] ==' '|| buf[i] == '\t' ) i++,j++;//去掉没有用的空格
int id = init_cmd ();//从内存池中取出一个命令的槽
if ( mode == 1 ) cmd[id].type |= PIPE;//如果命令位于中间位置,那么设置为属性包含PIPE属性
char* segment[MAX_ARGS];//存储划分段的位置的指针
int x=0;
for ( ; i < n ; i++ )
if ( buf[i] == ' ' || i == n-1 )
{
if ( buf[i] == ' ' ) buf[i] = 0;
segment[x++] = buf+j;
j = i+1;
while ( buf[j] == ' ' || buf[j] == '\t' )
j++,i++;
}
//分析指令,查找文件的重定向和向参数列表中添加参数
int temp = 0;
cmd[id].cmd = segment[0];
cmd[id].param = malloc(sizeof (char*)*(MAX_ARGS+2) );
if ( x > 0 )
cmd[id].param[temp++] = segment[0];
for ( i = 1; i < x ; i++ )
{
int flag = 1;
if ( strlen(segment[i]) == 1 )
{
if ( segment[i][0] == '<' )
{
flag = 0;
cmd[id].input = segment[i+1];
i++;
}
else if ( segment[i][0] == '>' )
{
flag = 0;
cmd[id].output = segment[i+1];
i++;
}
}
if ( strlen ( segment[i] ) == 2 )
{
if ( strcmp ( segment[i] , "<<" ) == 0 )
{
flag = 0;
cmd[id].input = segment[i+1];
i++;
}
else if ( strcmp ( segment[i] , ">>" ) == 0 )
{
flag = 0;
cmd[id].output = segment[i+1];
i++;
}
}
if ( flag )
{
cmd[id].param[temp++] = segment[i];
}
}
}


需要用到的函数库中的函数

string.h里的一些简单的字符串操作函数

char* flag = fgets ( buf , BUFSIZE , stdin);用于读取一行数据的函数,第一个是缓存区间的首地址,第二个为缓存区间的规模,第三个为输入流

malloc向堆申请内存
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell