使用strtok运行多个命令

问题描述 投票:1回答:2

我正在尝试使用C创建一个shell,它可以使用分号(;)分隔多个命令。目前我正在尝试使用strtok来分离命令,但我认为我没有正确使用它。我会在不发布完整代码的情况下发布所有信息。 strtok正确使用了吗?

char *semi=";";
 else
            {
                    char *token=strtok(str,semi);
                    if(token != NULL)
                    {
                            token=strtok(NULL,semi);
                    if((childpid = fork()) == 0)
                    {
                            if ((execvp(args[0], args))<0)//prints error message when unknown command is used
                            {
                                    printf("Error! Command not recognized.\n");
                            }
                            execvp(args[0],args);
                            free(args);//deallocate args
                            exit(0);
                    }

编辑:根据指示,我删除了最初发布的大部分代码,专注于使用strtok。编译时,临时shell将一次接受一个命令。我正在尝试使用“;”同时分离和运行两个命令。我正确使用strtok吗?如果没有,有替代方案吗?

c shell strtok
2个回答
1
投票

如果strtok()返回NULL,你应该经常检查。我会改变结构如下:

char* semi = ";"; // Your semikolon
char *token = NULL; // Your token string

// ...
// Split first occour of semicolon
token = strtok(str,semi);
if(token == NULL){
    perror("No command given ...");
    return NULL;
}
do {
    // Execute your code here
    // fork() etc.
    // You should get each line (each semikolon seperated string)
    // and it should be stored into token
} while((token = strtok(NULL, semi) != NULL);

我希望,我确实理解你的问题......

但正如我所看到的,你需要再次用空格分割token,使它们成为charargv[]execvp()(第二个参数)的strtok()数组。这里的问题是,static内部使用strtok()(?)变量来存储最后一个位置。所以在循环中使用另一个char *str; // Your string ... char semi[1] = ";"; // Your semikolon AND space; strtok() will split at both char *token = NULL; // Your token string int len = 0; char *token2; int argvpos = 0; // ... // Split first occour of semicolon token = strtok(str,semi); if(token == NULL){ perror("No command given ..."); return EXIT_FAILURE; } do { // save length of token len = strlen(token); // Split for blanks to get the arguments token2 = strtok(token," "); // Build array of arguments while(token2 != NULL){ args[argvpos++] = token2; token2 = strtok(NULL," "); } // Do something with token (as command) // and args (as arguments) // ... } while((token = strtok(token+len+1, semi) != NULL); // In the while condition you add the length to the token; so you get the "old" last position 会“破坏”你的文本。

你可以这样做:

strtok

我认为这不是一个好的解决方案,但它应该有效。我希望,我确实理解你的问题;-)

亲切的问候。


1
投票

为了正常工作,execvp应该与while循环一起使用。此外,您不需要运行#include <string.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main() { char str[] = "ls -1; echo 'hello world'"; // Input commands separated by ';' // Break the commands string into an array char *commands[10]; // Array to hold a max of 10 commands char *semi = ";"; char *token = strtok(str, semi); int i = 0; while (token != NULL) { commands[i] = token; ++i; token = strtok(NULL, semi); } int numCommands = i; // numCommands is the max number of input commands // Run each input command in a child process i = 0; while (i < numCommands) { printf("Command: %s\n", commands[i]); // Tokenize the command so that it can be run using execvp char *args[10] = {}; // Array to hold command args args[0] = strtok(commands[i], " "); int tokenCounter = 0; while (args[tokenCounter] != NULL) { tokenCounter++; args[tokenCounter] = strtok(NULL, " "); } // Create a child process int childpid = fork(); // If this is child process, run the command if (childpid == 0) { if ((execvp(args[0], args)) < 0) { printf("Error! Command not recognized.\n"); } exit(0); } // If this is the parent, wait for the child to finish else if (childpid > 0) { wait(&childpid); } // If the child process could not be created, print an error and exit else { printf("Error: Could not create a child process.\n"); exit(1); } ++i; } return 0; } 两次。

我使用您的代码创建了一个小示例程序,以演示如何正确使用您的代码:

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.