C++实现模拟shell命令行(代码解析)

目录
  • 一、解析
  • 二、执行命令函数
  • 三、模拟shell
  • 四、完整代码
  • 四、运行结果

一、解析

/**
 * 进行命令行解析:
 * 多个空格
 * 分割符:< > |
 * */
void parse(){
    std::string line;
    getline(std::cin, line);
    /** 解析字符串 */
    int len = line.size(), i=0;

    std::string tmp;
    std::vector<std::string> tmp_vc;
    while(i < line.size()){
        if(line[i] == ' '){
            i++;
            continue;
        }
        if(line[i] == '|') {
            vc.push_back(tmp_vc);
            tmp = "";
            i++;
            continue;
        }
        int pos = line.find(' ', i);    // 获取下一个空格的位置
        tmp = line.substr(i, pos-i);    // 截取字符串
        tmp_vc.push_back(tmp);
        i = pos;
    }
    vc.push_back(tmp_vc);
}

二、执行命令函数

/** 执行命令子函数 */
void func(std::vector<std::string>& v){
    char *arr[10];
    pid_t pid;
    pid = fork();
    if(pid == -1){
        std::cout << "fork error" << std::endl;
        exit(1);
    }else if(pid ==0){
        for(int i=0; i<v.size(); ++i)
            arr[i] = (char *)v[i].c_str();
        arr[v.size()] = NULL;
        execvp(arr[0], arr);
    }else{
        wait(NULL);
    }
}

/** 执行命令
 * --------
 * 创建子进程执行
 * 当出现|需要创建多个子进程
 * 当出现> <则将内容写入文件或者命令行
 * */
void execCommnd(){
    for(int i=0; i<vc.size(); ++i){
        func(vc[i]);
    }
}

三、模拟shell

/** 获取当前所在目录 */
void getCurPwd(){
    std::string s = get_current_dir_name();
    int pos  = s.rfind('/');
    std::string tmp = s.substr(pos+1, s.length()-pos);
    std::cout << tmp << "]# ";
}

/** 获取当前用户名 */
void getIdname(){
    struct  passwd *pwd;
    pwd = getpwuid(getuid());
    std::cout << "["  <<pwd->pw_name << "@";
}

/** 获取当前主机名 */
void getHostName(){
    char buf_w[128];
    int hostname = gethostname(buf_w, sizeof(buf_w));
    std::cout << buf_w << " ";

}

/** 显示菜单 */
void showMenu(){
    getIdname();
    getHostName();
    getCurPwd();
}

四、完整代码

/*----------------------------------------------------------------------
	> File Name: shellDemo.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Sun 19 Dec 2021 11:24:21 AM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <wait.h>

/* 存储命令以及参数 */
std::vector<std::vector<std::string>> vc;

/**
 * 进行命令行解析:
 * 多个空格
 * 分割符:< > |
 * */
void parse(){
    std::string line;
    getline(std::cin, line);
    /** 解析字符串 */
    int len = line.size(), i=0;

    std::string tmp;
    std::vector<std::string> tmp_vc;
    while(i < line.size()){
        if(line[i] == ' '){
            i++;
            continue;
        }
        if(line[i] == '|') {
            vc.push_back(tmp_vc);
            tmp = "";
            i++;
            continue;
        }
        int pos = line.find(' ', i);                // 获取下一个空格的位置
        tmp = line.substr(i, pos-i);    // 截取字符串
        tmp_vc.push_back(tmp);
        i = pos;
    }
    vc.push_back(tmp_vc);
}

/** 执行命令子函数 */
void func(std::vector<std::string>& v){
    char *arr[10];
    pid_t pid;
    pid = fork();
    if(pid == -1){
        std::cout << "fork error" << std::endl;
        exit(1);
    }else if(pid ==0){
        for(int i=0; i<v.size(); ++i)
            arr[i] = (char *)v[i].c_str();
        arr[v.size()] = NULL;
        execvp(arr[0], arr);
    }else{
        wait(NULL);
    }
}

/** 执行命令
 * --------
 * 创建子进程执行
 * 当出现|需要创建多个子进程
 * 当出现> <则将内容写入文件或者命令行
 * */
void execCommnd(){
    for(int i=0; i<vc.size(); ++i){
        func(vc[i]);
    }
}

/** 获取当前所在目录 */
void getCurPwd(){
    std::string s = get_current_dir_name();
    int pos  = s.rfind('/');
    std::string tmp = s.substr(pos+1, s.length()-pos);
    std::cout << tmp << "]# ";
}

/** 获取当前用户名 */
void getIdname(){
    struct  passwd *pwd;
    pwd = getpwuid(getuid());
    std::cout << "["  <<pwd->pw_name << "@";
}

/** 获取当前主机名 */
void getHostName(){
    char buf_w[128];
    int hostname = gethostname(buf_w, sizeof(buf_w));
    std::cout << buf_w << " ";

}

/** 显示菜单 */
void showMenu(){
    getIdname();
    getHostName();
    getCurPwd();
}

void test(){
    while(1){
        showMenu();
        parse();
        execCommnd();
    }
}

int main(int argc, char* argv[])
{
    test();
    return 0;
}

四、运行结果

到此这篇关于C++实现模拟shell命令行的文章就介绍到这了,更多相关C++ shell命令行内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++命令行解析包gflags的使用教程

    前言 gflags 是 Google 提供的一个命令行参数处理的开源库,目前已经独立开源,比传统的 getopt() 功能更加强大,可以将不同的参数定义分布到各个源码文件中,不需要集中管理. 提供了 C++ 和 Python 两个版本,这里仅详细介绍 C++ 版本的使用方式. 简介 配置参数分开还是集中管理没有严格的约束,关键要看项目里的统一规范,只是,gflags 可以支持这两种方式,允许用户更加灵活的使用. 当将参数分布到各个源码文件中时,如果定义了相同的参数,那么在编译的时候会直接报错.

  • C++执行shell命令的多种实现方法

    目录 1.system(执行shell 命令) 2.popen(建立管道I/O) 3.使用vfork()新建子进程,然后调用exec函数族 在linux系统下,用C++程序执行shell命令有多种方式 1.system(执行shell 命令) 相关函数:fork,execve,waitpid,popen 表头文件:#include<stdlib.h> 函数原型:int system(const char * string); 函数说明 :system()会调用fork()产生子进程,由子进程来

  • C++实现希尔排序(ShellSort)

    本文实例为大家分享了C++实现希尔排序的具体代码,供大家参考,具体内容如下 一.思路: 希尔排序:又称缩小增量排序,是一种改进的插入排序算法,是不稳定的. 设排序元素序列有n个元素,首先取一个整数gap<n作为间隔,将全部元素分为gap个子序列,所有距离为gap的元素放在同一个子序列中,在每一个子序列中分别施行直接插入排序.然后缩小间隔gap,重复上述的子序列和排序工作. 二.实现程序: #include <iostream> using namespace std; const int

  • 用C++实现一个命令行进度条的示例代码

    缘起 最近做遥感影像融合的GWPCA方法,在带宽比较大的时候速度太慢了,需要有个进度条指示一下,然后我去找进度条的库,发现github上面的C/C++的相应的库似乎没有能在VS下跑的,自己花了点时间写了一个. 效果 实现 大概需要考虑这样几个要素 已完成的百分比 执行速度 已执行的时间 剩余时间 另外进度条的引入不能破坏已有的执行结构,最好和Python的tqdm库类似,通过 start , update 等函数来完成整个进度条,因此对于C语言来说,需要一个定时器,定期将进度条进行重绘(不可能更

  • C++实现模拟shell命令行(代码解析)

    目录 一.解析 二.执行命令函数 三.模拟shell 四.完整代码 四.运行结果 一.解析 /** * 进行命令行解析: * 多个空格 * 分割符:< > | * */ void parse(){ std::string line; getline(std::cin, line); /** 解析字符串 */ int len = line.size(), i=0; std::string tmp; std::vector<std::string> tmp_vc; while(i &l

  • 使用Apache commons-cli包进行命令行参数解析的示例代码

    Apache的commons-cli包是专门用于解析命令行参数格式的包. 依赖: <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.3.1</version> </dependency> 使用此包需要: 1.先定义有哪些参数需要解析.哪些参数有额外的选项.每个参数的描述等等,对应

  • shell 命令统计代码行数的简单代码

    分享一个统计代码行的shell命令: find . "(" -name ".java" -or -name ".html" -or -name ".js" -or -name ".css" ")" -print | xargs wc -l 根据不同的项目类型,不同的目录,自行修改. 如果内容多,可以: find . "(" -name ".java"

  • Python中的命令行参数解析工具之docopt详解

    前言 docopt 是一个开源的库,代码地址:https://github.com/docopt/docopt.它在 README 中就已经做了详细的介绍,并且还附带了很多例子可供学习,这篇文章也是翻译一下 README 中内容-- docopt 最大的特点在于不用考虑如何解析命令行参数,而是当你把心中想要的格式按照一定的规则写出来后,解析也就完成了. docopt的安装 docopt有很多种版本,分别支持不同的语言,最简答的docopt支持python脚本,docopt.java支持java脚

  • Python命令行参数解析工具 docopt 安装和应用过程详解

    什么是 docopt? 1.docopt 是一种 Python 编写的命令行执行脚本的交互语言. 它是一种语言! 它是一种语言! 它是一种语言! 2.使用这种语言可以在自己的脚本中,添加一些规则限制.这样脚本在执行的时候就必须按照这样格式来执行,同时,也可以很方便的编写一些帮助信息(其实很多软件在输入 -h 的时候显示信息 .例如 python -h ,会显示所有的 python 指令,并且页通过 docopt 限制了 python 指令的格式),下面是一些简单的例子: docopt 的安装 d

  • python命令行参数解析OptionParser类用法实例

    本文实例讲述了python命令行参数解析OptionParser类的用法,分享给大家供大家参考. 具体代码如下: from optparse import OptionParser parser = OptionParser(usage="usage:%prog [optinos] filepath") parser.add_option("-t", "--timeout", action = "store", type =

  • 详解Shell 命令行批量处理图片文件名的实例

    Shell 命令行批量处理图片文件名 前言: 从网上下载了一堆图片,有的是*.jpg的,有的是*.jpeg的.并且文件名有长有短,很是糟心.因此,我想把这些文件给全部整理好,当然是用shell来处理啦! 说干就干. 循环所有文件 首先,我把所有的乱七八糟的图片,全部放在 ./image/ 这个文件夹下面. 然后在外层写一个i.sh的shell文件,录入下面的内容. 我的文件结构演示如下: 文件 image/xxx.jpg image/xxx.jpeg i.sh for f in $(find .

  • Linux 命令行工具解析和格式化输出 JSON的方法

    JSON 是一种轻量级且与语言无关的数据存储格式,易于与大多数编程语言集成,也易于人类理解 -- 当然,如果格式正确的话.JSON 这个词代表 J ava S cript O bject N otation,虽然它以 JavaScript 开头,而且主要用于在服务器和浏览器之间交换数据,但现在正在用于许多领域,包括嵌入式系统.在这里,我们将使用 Linux 上的命令行工具解析并格式化打印 JSON.它对于在 shell 脚本中处理大型 JSON 数据或在 shell 脚本中处理 JSON 数据非

  • jupyter notebook 参数传递给shell命令行实例

    我就废话不多说了,大家看代码吧! dataset = ["el","tv"] model = ["model"] stride = [32,64,256,512] for m in model: for d in dataset: for s in stride: print(f"{m} {d} {s}") c = f"tail -n3 N{m}_hp_emb{s}_adam_{d}_log_1.txt"

  • Python 利用argparse模块实现脚本命令行参数解析

    study.py内容如下 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'shouke' import argparse def argparseFunc(): ''' 基于argparse模块实现命令参数解析功能 执行示例: python study.py -i 172.19.7.236 -p 8080 -a -r python study.py --ip 172.19.7.236 --port 7077 --auth -w

随机推荐