Shell實現(三)讀取命令的實現
阿新 • • 發佈:2019-01-28
基本思路
- 讀取命令我採取的讀取整個字串後再進行分段和分析:
- 首先是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向堆申請記憶體