在 C 中解析 bash 命令输入
Parsing bash command input in C
我正在用 C 编写一个简单的 shell。shell 的一部分使用了需要拆分为字符数组的 bash 命令,这样我就可以正确执行命令。作为一个简单的概念证明,我想编写一个 C 程序来检查它是一个单词还是一个特殊字符(|
、&
、>
和 <
).
下面是它的外观示例:
input a command: cat hello.txt |wc -l
---output---
cat
hello.txt
|
wc
-l
到目前为止,我已经让每个案例都起作用了,例如,除了一个,那就是当我在 |wc l
中做一个特殊字符时,其中一个字母是 after 特殊字符。这是我当前的输出:
input a command: cat hello.txt |wc -l
---output---
cat
hello.txt
|wc
-l
下面是我的代码,我试过添加特殊情况、删除情况,但似乎没有什么能正常工作。我该如何解决?
#include <stdio.h>
#include <string.h>
#define ALPHABET 1000
#define LESS_THAN 60
#define GREATER_THAN 62
#define AMPERSAND 38
#define PIPE 124
#define WHITESPACE 32
#define NEWLINE 10
#define MYCOPOUT 9999
#define CAPITALS(i) ((i >= 65) && (i <= 90))
#define LOWERS(i) ((i >= 97) && (i <= 122))
#define BACKSLASH(i) i == 47
int classify(int i)
{
if (CAPITALS(i) || LOWERS(i) || BACKSLASH(i))
return ALPHABET;
return i;
}
char isSpecial(int i)
{
return (i == LESS_THAN) ||(i == GREATER_THAN) || (i == AMPERSAND) || (i == PIPE);
}
char isWhiteSpace(int i)
{
return (i == WHITESPACE) || (i == NEWLINE);
}
void PRINT_N_NEW(int c, int last)
{
if (isWhiteSpace(last)) {
printf("%c",c);
} else if(isSpecial(last)) {
printf("\n%c\n",c);
} else {
printf("%c\n", c);
}
last = c;
}
int main(int argc, char** argv)
{
int i;
int last = MYCOPOUT;
while ( (i = getchar()) != EOF){
switch(classify(i)){
case ALPHABET:
printf("%c",i);
last = i;
break;
case LESS_THAN:
PRINT_N_NEW(i,last);
break;
case GREATER_THAN:
PRINT_N_NEW(i,last);
break;
case AMPERSAND:
PRINT_N_NEW(i,last);
break;
case PIPE:
PRINT_N_NEW(i,last);
break;
case WHITESPACE:
printf("\n");
last = i;
break;
case NEWLINE:
printf("\n");
last = i;
break;
default:
printf("%c",i);
last = i;
break;
}
}
return 0;
}
你可以使用 strtok 吗?
http://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
尝试用“ ”符号分隔子字符串,这可能会有用
为了解决这个问题,你可以检查令牌的第一个字符是否是一个符号
if (令牌[0] == "|")
aux_str = 代币+1;
可能是这样的:
enter code here
#define (CMD_SEPARATORS) ("|<>&")
int function interpretCMD(char *s){
char **args = malloc (sizeof(char*) * MAX_ARGS);
cmd = strtok (s, " ");
args = strtok(s);
while (cmd != NULL){
args[i] = strtok(s);
}
/*
at this point you must have cmd the cmd
and in args[i] the i argument
*/
}
int function parseCMD(char *s){
cmd = strtok(s, CMD_SEPARATORS);
while (cmd!= NULL){
interpretCMD(token);
cmd = strtok(s);
}
}
main blablah
while ( (line = getline()) != EOF){
parseCMD(line);
}
您的代码运行良好,
if (isWhiteSpace(last)) {
printf("%c\n",c);
在此打印语句中放置新行。或者在管道到来后放置新行。
您不会在每次循环时都设置 last
,只是在 switch
的某些情况下。你也应该在打印普通字符时使用 PRINT_N_NEW
,这样它会测试最后一个字符并在它之前放一个换行符。最后,如果你要打印的字符是一个特殊字符,你需要在它之前打印一个换行符。
在 PRINT_N_NEW
结束时做 last = c
没有意义。这不会在调用者中设置变量,它只是设置本地副本。
#include <stdio.h>
#include <string.h>
#define ALPHABET 1000
#define LESS_THAN 60
#define GREATER_THAN 62
#define AMPERSAND 38
#define PIPE 124
#define WHITESPACE 32
#define NEWLINE 10
#define MYCOPOUT 9999
#define CAPITALS(i) ((i >= 65) && (i <= 90))
#define LOWERS(i) ((i >= 97) && (i <= 122))
#define BACKSLASH(i) i == 47
int classify(int i)
{
if (CAPITALS(i) || LOWERS(i) || BACKSLASH(i))
return ALPHABET;
return i;
}
char isSpecial(int i)
{
return (i == LESS_THAN) ||(i == GREATER_THAN) || (i == AMPERSAND) || (i == PIPE);
}
char isWhiteSpace(int i)
{
return (i == WHITESPACE) || (i == NEWLINE);
}
void PRINT_N_NEW(int c, int last)
{
if (isWhiteSpace(last)) {
printf("%c",c);
} else if(isSpecial(last) || isSpecial(c)) {
printf("\n%c",c);
} else {
printf("%c", c);
}
}
int main(int argc, char** argv)
{
int i;
int last = MYCOPOUT;
while ( (i = getchar()) != EOF){
switch(classify(i)){
case ALPHABET:
PRINT_N_NEW(i, last);
break;
case LESS_THAN:
PRINT_N_NEW(i,last);
break;
case GREATER_THAN:
PRINT_N_NEW(i,last);
break;
case AMPERSAND:
PRINT_N_NEW(i,last);
break;
case PIPE:
PRINT_N_NEW(i,last);
break;
case WHITESPACE:
printf("\n");
break;
case NEWLINE:
printf("\n");
break;
default:
PRINT_N_NEW(i, last);
break;
}
last = i;
}
return 0;
}
我正在用 C 编写一个简单的 shell。shell 的一部分使用了需要拆分为字符数组的 bash 命令,这样我就可以正确执行命令。作为一个简单的概念证明,我想编写一个 C 程序来检查它是一个单词还是一个特殊字符(|
、&
、>
和 <
).
下面是它的外观示例:
input a command: cat hello.txt |wc -l
---output---
cat
hello.txt
|
wc
-l
到目前为止,我已经让每个案例都起作用了,例如,除了一个,那就是当我在 |wc l
中做一个特殊字符时,其中一个字母是 after 特殊字符。这是我当前的输出:
input a command: cat hello.txt |wc -l
---output---
cat
hello.txt
|wc
-l
下面是我的代码,我试过添加特殊情况、删除情况,但似乎没有什么能正常工作。我该如何解决?
#include <stdio.h>
#include <string.h>
#define ALPHABET 1000
#define LESS_THAN 60
#define GREATER_THAN 62
#define AMPERSAND 38
#define PIPE 124
#define WHITESPACE 32
#define NEWLINE 10
#define MYCOPOUT 9999
#define CAPITALS(i) ((i >= 65) && (i <= 90))
#define LOWERS(i) ((i >= 97) && (i <= 122))
#define BACKSLASH(i) i == 47
int classify(int i)
{
if (CAPITALS(i) || LOWERS(i) || BACKSLASH(i))
return ALPHABET;
return i;
}
char isSpecial(int i)
{
return (i == LESS_THAN) ||(i == GREATER_THAN) || (i == AMPERSAND) || (i == PIPE);
}
char isWhiteSpace(int i)
{
return (i == WHITESPACE) || (i == NEWLINE);
}
void PRINT_N_NEW(int c, int last)
{
if (isWhiteSpace(last)) {
printf("%c",c);
} else if(isSpecial(last)) {
printf("\n%c\n",c);
} else {
printf("%c\n", c);
}
last = c;
}
int main(int argc, char** argv)
{
int i;
int last = MYCOPOUT;
while ( (i = getchar()) != EOF){
switch(classify(i)){
case ALPHABET:
printf("%c",i);
last = i;
break;
case LESS_THAN:
PRINT_N_NEW(i,last);
break;
case GREATER_THAN:
PRINT_N_NEW(i,last);
break;
case AMPERSAND:
PRINT_N_NEW(i,last);
break;
case PIPE:
PRINT_N_NEW(i,last);
break;
case WHITESPACE:
printf("\n");
last = i;
break;
case NEWLINE:
printf("\n");
last = i;
break;
default:
printf("%c",i);
last = i;
break;
}
}
return 0;
}
你可以使用 strtok 吗?
http://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
尝试用“ ”符号分隔子字符串,这可能会有用
为了解决这个问题,你可以检查令牌的第一个字符是否是一个符号
if (令牌[0] == "|") aux_str = 代币+1;
可能是这样的:
enter code here
#define (CMD_SEPARATORS) ("|<>&")
int function interpretCMD(char *s){
char **args = malloc (sizeof(char*) * MAX_ARGS);
cmd = strtok (s, " ");
args = strtok(s);
while (cmd != NULL){
args[i] = strtok(s);
}
/*
at this point you must have cmd the cmd
and in args[i] the i argument
*/
}
int function parseCMD(char *s){
cmd = strtok(s, CMD_SEPARATORS);
while (cmd!= NULL){
interpretCMD(token);
cmd = strtok(s);
}
}
main blablah
while ( (line = getline()) != EOF){
parseCMD(line);
}
您的代码运行良好,
if (isWhiteSpace(last)) {
printf("%c\n",c);
在此打印语句中放置新行。或者在管道到来后放置新行。
您不会在每次循环时都设置 last
,只是在 switch
的某些情况下。你也应该在打印普通字符时使用 PRINT_N_NEW
,这样它会测试最后一个字符并在它之前放一个换行符。最后,如果你要打印的字符是一个特殊字符,你需要在它之前打印一个换行符。
在 PRINT_N_NEW
结束时做 last = c
没有意义。这不会在调用者中设置变量,它只是设置本地副本。
#include <stdio.h>
#include <string.h>
#define ALPHABET 1000
#define LESS_THAN 60
#define GREATER_THAN 62
#define AMPERSAND 38
#define PIPE 124
#define WHITESPACE 32
#define NEWLINE 10
#define MYCOPOUT 9999
#define CAPITALS(i) ((i >= 65) && (i <= 90))
#define LOWERS(i) ((i >= 97) && (i <= 122))
#define BACKSLASH(i) i == 47
int classify(int i)
{
if (CAPITALS(i) || LOWERS(i) || BACKSLASH(i))
return ALPHABET;
return i;
}
char isSpecial(int i)
{
return (i == LESS_THAN) ||(i == GREATER_THAN) || (i == AMPERSAND) || (i == PIPE);
}
char isWhiteSpace(int i)
{
return (i == WHITESPACE) || (i == NEWLINE);
}
void PRINT_N_NEW(int c, int last)
{
if (isWhiteSpace(last)) {
printf("%c",c);
} else if(isSpecial(last) || isSpecial(c)) {
printf("\n%c",c);
} else {
printf("%c", c);
}
}
int main(int argc, char** argv)
{
int i;
int last = MYCOPOUT;
while ( (i = getchar()) != EOF){
switch(classify(i)){
case ALPHABET:
PRINT_N_NEW(i, last);
break;
case LESS_THAN:
PRINT_N_NEW(i,last);
break;
case GREATER_THAN:
PRINT_N_NEW(i,last);
break;
case AMPERSAND:
PRINT_N_NEW(i,last);
break;
case PIPE:
PRINT_N_NEW(i,last);
break;
case WHITESPACE:
printf("\n");
break;
case NEWLINE:
printf("\n");
break;
default:
PRINT_N_NEW(i, last);
break;
}
last = i;
}
return 0;
}