shell 数组元素有空格_【C语言|Linux】简易的 shell 实现

这是一个适合初学者的Linux进程学习项目,介绍如何在shell中处理包含空格的数组元素。文章涵盖了功能演示、源码分享以及输入处理的三个步骤,包括解析输入和使用exec函数执行命令。特别提到,由于exec只能替换第一种命令,因此shell中的cd命令无效。
摘要由CSDN通过智能技术生成

这个小程序适合初学者在学习 Linux 进程时,对这部分知识的复习巩固。尤其是 exec系和 wait系 函数的应用。

就像题目说的那样,这是一个简易的 shell,以后有机会可能会出功能比较全面的 shell,敬请期待~

1. 功能演示

946770eb56bde8e2d8e8ef18f7eedc18.png

视频讲解:https://b23.tv/wK5Iys

2. 源码分享

1. 处理输入

我们在使用 shell 时,肯定会输入很多数据,我们先获取输入的数据,将其保存在一个缓冲区中。

  int get_input(char buf[]){
    
    int ret, ch; 
    
    memset(buf, 0x00, BUFFSIZE);
  
    // %*c 用来回收正常输入命令后面的回车键
    // 如果只输入回车键,因为 scanf 的第一个参数就不匹配,scanf 直接返回,回车键不会被处理
    ret = scanf("%[^n]%*c", buf);
    
    // 处理只输入回车的情况
    // 添加 if 判断时处理输入 空格加回车的情况
    if(ret == 0){
        ch = getchar();
    }                                                                                                                         
    return ret;
  }

2. 解析输入

一般我们在输入命令时,肯定不会规规矩矩的(=_=

所以,我们需要处理输入的数据,设置一个字符串指针数组 argv,然后让它的元素指向我们解析好的一个个单词。这样做的好处是:第三步处理输入时,可以将 argv 直接作为 execvp 函数的第二个参数。

  void parse(char* buf){
  
    int i, flg = OUT;
    int argc = 0;
    char* argv[MAX_CMD];                                                                                                                         
  
    for(i = 0; buf[i] != '0'; i++){
      // 进入单词
      if(flg == OUT && !isspace(buf[i])){
        // 状态设置为 IN 
        flg = IN;
        // argv 成员指向 buf 字符数组中单词的开始
        argv[argc++] = buf + i;
      }
      // 离开单词
      else if(flg == IN && isspace(buf[i])){
        // 状态设置为 OUT 
        flg = OUT;
        // 单词结束处设置终止字符
        buf[i] = '0';
      }
    }
  
    // 因为进程替换我们要使用 execvp 函数,argv 指针数组应该符合参数格式 
    argv[argc] = NULL;
  
    do_cmd(argc, argv); // 执行命令
  }

3. 处理输入

shell 命令分为四种:

  • 可执行程序:/usr/bin 中看到的所有文件一样。
  • shell 内置命令: bash 支持的成为 shell builtin 的内置命令。例如,cd
  • shell 函数: 合并到环境变量中的小型 shell 脚本。
  • alias 命令: 在其他命令的基础上定义自己的命令

其中可执行程序的实现就是 fork 出子进程然后使用 exec 函数进行进程替换。

这里要注意的是,exec 只能替换第一种命令。所以 cd 命令无效,这样工作目录就没法更改了。

void do_cmd(int argc, char* argv[]){
                                                                                                                                                 
    pid_t pid;
  
    switch(pid = fork()) {
      // 如果 fork 出错,可以提示维护信息
      case -1:
              printf("当前 shell 维护中...");
              return;
      // 处理子进程
      case 0:
               execvp(argv[0], argv);
               // 如果子进程被成功替换,就不可能执行下面的代码
               printf("%s: command not foundn", argv[0]);
               exit(1);
             
      default: {
                 int status;
                 waitpid(pid, &status, 0); //等待子进程返回
                 // 处理子进程的返回码
               }
              break;
    }
  }

main 函数就相当简单了,这里就不写了。

源代码获取

源代码获取方式在原文文末,原文链接: https:// mp.weixin.qq.com/s/wUzH L4DYsf2_o_Zs59qB8A

如果你对这个代码有任何问题,欢迎和我交流!

C/C++/Java 方向学习资料分享,持续更新:

6617917537f3690eb55288836a0ec3d0.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值