PART 2: 使 Shell 能读取命令

这篇文章是《动手写 Shell》系列文章的第 <2> 篇。上篇文章中,我们已经完成了我们动手 Shell 的第一步:Shell 的提示符。在这篇文章中,我们开始使得我们的 Shell 能够开始读取命令,并且做简单的分词,将命令与参数分开。

读取命令

0x00 readline 库的使用

在实现读取命令的方法中我们所使用到的库是 readline,其实我们使用 fgets() 方法也能达到目的,但是如果使用 fgets() 的话如果我们在使用 Shell 时输入错了命令不能通过退格键来撤销,因为 fgets() 是按字符进行读取的。

0x01 安装 readline 库

sudo apt-get install libreadline-dev

0x02 使用 readline 库

如果我们的程序中使用到了该库,需要在编译代码时需要链接到 libreadline

例:

gcc -o test test.o -I /usr/include -lreadline

处理命令

0x00 实现思路

对于一条命令

cmd para1 para2 […… paraN]

我们希望它能被识别成为:

命令: cmd

参数0: cmd

参数1: para1

参数2: para2

……

参数N: paraN

其实思路也是很简单:

我们需要一个command指针来存储命令,一个数组来存储命令。

需要两个指针来顺着我们的整条指令来移动,来获取到每一个命令或者参数。

一开始时:

两个指针 *start, *end都指向指令的开头

如果 *start, *end 指向空格,自动向后移动

定义一个计数器 count,然后 *end 指针开始向后移动,直到碰到空格或者换行符或者结束符

如果 count 为0,说明当前处理的是命令,定一个临时指针 *p,沿着 *end*start 移动,将其赋给 *commandparameter[0]count + 2.

如果 *end 为换行符或终止符则停止,否则,将 *end 赋给 *start,然后 *end 按上述方式继续向后移动,直到遇到空格,将 *start 赋给 parameters[count-1]count + 1.

重复以上工作,直到 *end 遇到终止符 \0 或者换行符 \n

0x01 实现代码

#include "lshell.h"
#include <readline/readline.h>
#include <readline/history.h>

int read_command(char **command, char **parameters, char *prompt)
{
    free(buffer);
    buffer = readline(prompt);
    if(feof(stdin))
    {
        printf("\n");
        exit(0);
    }

    if(buffer[0] == ‘\0‘)
    {
        return -1;
    }

    int count = 0;
    char *start, *end;
    int isFinished = 0;

    start = end = buffer;

    while(isFinished == 0)
    {
        while((*start == ‘ ‘ && *end == ‘ ‘) || (*start == ‘\t‘ && *end == ‘\t‘))
        {
            start++;
            end++;
        }

        if(*end == ‘\0‘ || *end == ‘\n‘)
        {
            if(count == 0)
            {
                return -1;
            }
            break;
        }

        while(*end != ‘\0‘ && *end != ‘\n‘ && *end != ‘ ‘)
        {
            end++;
        }

        if(count == 0){
            char *p = end;
            *command = start;

            while(p != start && *p != ‘/‘){
                p--;
            }

            if(*p == ‘/‘){
                p++;
            }

            parameters[0] = p;
            count += 2;

#ifdef DEBUG
            printf("\ncommand:%s\n", *command);
#endif // DEBUG
        }
        else if(count <= MAX_ARGS){
            parameters[count-1] = start;
            count++;
        }
        else{
            break;
        }

        if(*end = ‘\0‘ || *end == ‘\n‘){
            *end = ‘\0‘;
            isFinished = 1;
        }
        else{
            *end = ‘\0‘;
            end++;
            start = end;
        }

    }
    parameters[count-1] = NULL;

#ifdef DEBUG
    printf("input analysis:\n");
    printf("command:[%s]\ncommand:[%s]\nparameters:\n",*command,parameters[0]);
    int i;
    for(i=0;i<count-1;i++)
        printf("[%s]\n",parameters[i]);
#endif
    return count;
}

完整代码详见:https://github.com/luoyhang003/linux_kernel_expriment/tree/master/exp2


本文的版权归作者 罗远航 所有,采用 Attribution-NonCommercial 3.0 License。任何人可以进行转载、分享,但不可在未经允许的情况下用于商业用途;转载请注明出处。感谢配合!

时间: 2024-10-06 10:17:00

PART 2: 使 Shell 能读取命令的相关文章

Bash Shell内建命令和保留字

Bash Shell内建命令和保留字命令含义!保留字,逻辑非:不做任何事,只做参数展开.读取文件并在shell中执行它alias设置命令或命令行别名bg将作业置于后台运行bind将关键字序列与readline函数或宏捆绑break保留字,跳出for.while.until.select循环builtin调用命令的内建命令格式,而禁用同名的函数.或者同名的扩展命令case保留字,多重选择cd切换当前工作目录command找出内建和外部命令:寻找内建命令而非同名函数continue保留字,到达下次f

Linux 基础知识:Bash Shell 内置命令

bash内置命令无须搜寻环境变量$PATH中提供的路径,直接可以执行,因此速度很快. 以下介绍几个简单.必备的命令用法. 1. help 用途:显示所有bash内置命令的列表,或某一个内置命令的用法. 用法: 4help 执行结果:显示所有内置命令的列表. 4help –s 内置命令 执行结果:显示内置命令的语法格式. 用例: help cd 显示cd命令的详细用法. help –s printf printf: printf [-v var] format [arguments] 显示prin

Shell 脚本常用命令

Shell脚本是Linux开发工作中常用的工具,但是我一直没有找到一个适合自己的简明扼要的HandBook.在工作过程中整理了一下,贴在这里已备查看. 1           Shell中的特殊符号 1.1           $  美元符号.用来表示变量的值.如变量NAME的值为Mike,则使用$NAME就可以得到“Mike”这个值. 1.2          #  井号.除了做为超级用户的提示符之外,还可以在脚本中做为注释的开头字母,每一行语句中,从#号开始的部分就不执行了. 1.3    

shell中set命令

set命令作用主要是显示系统中已经存在的shell变量,以及设置shell变量的新变量值.set命令不能够定义新的shell变量.如果要定义新的变量,可以使用declare命令以变量名=值的格式进行定义即可. -a:标示已修改的变量,以供输出至环境变量. -b:使被中止的后台程序立刻回报执行状态. -C:转向所产生的文件无法覆盖已存在的文件. -d:Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行.使用-d参数可取消. -e:若指令传回值不等于0,则立即退出shell. -f:取消使用

Linux学习闲谈(一)——Shell基本操作与命令

Linux学习闲谈(一) --Shell基本操作与命令 (转载请附上本文链接--linhxx) 1.#!/bin/sh 放在程序开头,表示用/bin/sh方式来解析. 2.变量 1)变量赋值 varname='xxx',除了在变量赋值和在FOR循环语句头中,其他情况下BASH 中的变量使用必须在变量前加"$"符号,即采用 $varname使用变量.更为标准的变量引用方式是 ${STR} 这样的,$STR 自不过是对 ${STR} 的一种简化.在复杂情况下(即有可能产生歧义的地方)最好用

shell脚本常用命令(HandBook_2)

8            逻辑判断 8.1          if 8.1.1     单格式与嵌套 if 条件表达式  then #当条件为真时执行以下语句  命令列表  else #为假时执行以下语句  命令列表  fi  if 语句也可以嵌套使用   if 条件表达式1  then  if 条件表达式2  then  命令列表  else  if 条件表达式3  then  命令列表  else  命令列表  fi  fi  else  命令列表  fi  8.1.2     多分支格式

Shell 变量/echo命令

Shell 教程 Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务. Ken Thompson的sh是第一种Unix Shell,Windows Explorer是一个典型的图形界面Shell. Shell 脚本 Shell 脚本(shell script),是一种为shell编写的脚本程序. 业界所说的shell通常都是指she

shell 脚本 常用命令

Shell脚本是Linux开发工作中常用的工具,但是我一直没有找到一个适合自己的简明扼要的HandBook.在工作过程中整理了一下,贴在这里已备查看. 1           Shell中的特殊符号 1.1           $  美元符号.用来表示变量的值.如变量NAME的值为Mike,则使用$NAME就可以得到“Mike”这个值. 1.2          #  井号.除了做为超级用户的提示符之外,还可以在脚本中做为注释的开头字母,每一行语句中,从#号开始的部分就不执行了. 1.3    

Shell、内外部命令——Linux基本命令(2)

1.Shell Shell是Linux系统的用户界面,提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令并把它送入内核去执行. shell也被称为LINUX的命令解释器(commandinterpreter). vshell是一种高级程序设计语言. 2.bash shell GNUBourne-AgainShell(bash)是GNU计划中重要的工具软件之一,目前也是Linux标准的shell,与sh兼容. (1)查询当前系统使用哪个Shell 使用echo$SHELL echo的作用