C++實(shí)現(xiàn)模擬shell命令行(代碼解析)
一、解析
/**
* 進(jìn)行命令行解析:
* 多個(gè)空格
* 分割符:< > |
* */
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); // 獲取下一個(gè)空格的位置
tmp = line.substr(i, pos-i); // 截取字符串
tmp_vc.push_back(tmp);
i = pos;
}
vc.push_back(tmp_vc);
}
二、執(zhí)行命令函數(shù)
/** 執(zhí)行命令子函數(shù) */
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);
}
}
/** 執(zhí)行命令
* --------
* 創(chuàng)建子進(jìn)程執(zhí)行
* 當(dāng)出現(xiàn)|需要?jiǎng)?chuàng)建多個(gè)子進(jìn)程
* 當(dāng)出現(xiàn)> <則將內(nèi)容寫(xiě)入文件或者命令行
* */
void execCommnd(){
for(int i=0; i<vc.size(); ++i){
func(vc[i]);
}
}
三、模擬shell
/** 獲取當(dāng)前所在目錄 */
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 << "]# ";
}
/** 獲取當(dāng)前用戶名 */
void getIdname(){
struct passwd *pwd;
pwd = getpwuid(getuid());
std::cout << "[" <<pwd->pw_name << "@";
}
/** 獲取當(dāng)前主機(jī)名 */
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>
/* 存儲(chǔ)命令以及參數(shù) */
std::vector<std::vector<std::string>> vc;
/**
* 進(jìn)行命令行解析:
* 多個(gè)空格
* 分割符:< > |
* */
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); // 獲取下一個(gè)空格的位置
tmp = line.substr(i, pos-i); // 截取字符串
tmp_vc.push_back(tmp);
i = pos;
}
vc.push_back(tmp_vc);
}
/** 執(zhí)行命令子函數(shù) */
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);
}
}
/** 執(zhí)行命令
* --------
* 創(chuàng)建子進(jìn)程執(zhí)行
* 當(dāng)出現(xiàn)|需要?jiǎng)?chuàng)建多個(gè)子進(jìn)程
* 當(dāng)出現(xiàn)> <則將內(nèi)容寫(xiě)入文件或者命令行
* */
void execCommnd(){
for(int i=0; i<vc.size(); ++i){
func(vc[i]);
}
}
/** 獲取當(dāng)前所在目錄 */
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 << "]# ";
}
/** 獲取當(dāng)前用戶名 */
void getIdname(){
struct passwd *pwd;
pwd = getpwuid(getuid());
std::cout << "[" <<pwd->pw_name << "@";
}
/** 獲取當(dāng)前主機(jī)名 */
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;
}
四、運(yùn)行結(jié)果

到此這篇關(guān)于C++實(shí)現(xiàn)模擬shell命令行的文章就介紹到這了,更多相關(guān)C++ shell命令行內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析為何要關(guān)閉數(shù)據(jù)庫(kù)連接,可不可以不關(guān)閉的問(wèn)題詳解
本篇文章是對(duì)為何要關(guān)閉數(shù)據(jù)庫(kù)連接,可不可以不關(guān)閉的問(wèn)題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語(yǔ)言實(shí)現(xiàn)通訊錄的方法(包括靜態(tài)版本和動(dòng)態(tài)版本)
本文給大家分享C語(yǔ)言實(shí)現(xiàn)通訊錄的方法(包括靜態(tài)版本和動(dòng)態(tài)版本),針對(duì)每種方法給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-09-09
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的三子棋小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
C++實(shí)現(xiàn)LeetCode(89.格雷碼)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(89.格雷碼),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C語(yǔ)言中switch語(yǔ)句基本用法實(shí)例
switch的中文翻譯是開(kāi)關(guān),顧名思義,開(kāi)關(guān)的作用就是控制連通或者中斷,在C語(yǔ)言中switch語(yǔ)句的作用也是大同小異,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中switch語(yǔ)句基本用法的相關(guān)資料,需要的朋友可以參考下2022-07-07
c語(yǔ)言 樹(shù)的基礎(chǔ)知識(shí)(必看篇)
下面小編就為大家?guī)?lái)一篇c語(yǔ)言 樹(shù)的基礎(chǔ)知識(shí)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
C++異常處理方式實(shí)例詳解(超級(jí)詳細(xì)!)
程序有時(shí)會(huì)遇到運(yùn)行階段錯(cuò)誤,導(dǎo)致程序無(wú)法正常執(zhí)行下去,c++異常為處理這種情況提供了一種功能強(qiáng)大的而靈活的工具,下面這篇文章主要給大家介紹了關(guān)于C++異常處理方式的相關(guān)資料,需要的朋友可以參考下2023-04-04
C++ vector容器 find erase的使用操作:查找并刪除指定元素
這篇文章主要介紹了C++ vector容器 find erase的使用操作:查找并刪除指定元素,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05

