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

基本思路


  • 读取命令我采取的读取整个字符串后再进行分段和分析:
    • 首先是parse_token将字符串通过分号为分隔,得到每组命令,每组命令当中只包含管道,输入输出重定向和单条命令及其参数。
    • 然后是parse_group将每段得到的字符串通过管道为分隔,得到只包含参数,输入输出重定向和单条命令的更加简单的命令串
    • 最后是parse_command分析单条指令,得到输入输出重定向的文件流和命令的属性还有命令的参数。
    • 从内存中取出占位放入命令,然后将命令分组(组内连续)

具体实现:

  • 首先是parse_token
//遍历字符串以";"为分隔得到字符串组,用0取代;代表字符串结束,实现字符串的划分
void parse_token ( char* buf )
{
    int n = strlen ( buf ),i,j=0;
    n--;
    buf[n] = 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向堆申请内存
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值