我应该选择哪种方式进行Shell命令解析?

时间:2019-05-26 19:35:15

标签: c shell pipe io-redirection

为了学习,我必须用C制作外壳

我想解析一个shell命令

我的函数parse_sequence输出一个command_t *,它是一个包含以下内容的结构:

char *program_name;
int fd_input;
bool override;
int fd_output;
bool heredoc_mode;
char **args;
command_t *next; // kind of linked_list

我所说的序列是带有重定向和管道的命令

序列被&&||;削减

ls > file | sort是单个序列,其中ls && echo OK由两个序列组成

我在两种实现解析的方法之间犹豫不决

将此视为伪代码

第一种方式:递归

command_t *parse_sequence(char *sequence)
{
    command_t *ret = malloc(sizeof(command_t));
    char **tokens = split(sequence);
    int i = 0;

    while (tokens[i]) {
        if (!strcmp(commands[i], "<")) {
            // set input file (open commands[i + 1])
        }
        if (!strcmp(commands[i], ">")) {
            // set output file (open commands[i + 1])
        }
        if (!strcmp(commands[i], "|")) {
            // recursion: ret->next = parse_sequence(tokens[i + 1]);
        }
        else {
            if (i == 0)
                // set program name
            else
                // append args 
        }
    }
    return (ret);
}

示例ls > file | sort --rev

i == 0: ls is set as program_name
i == 1: ++i (file) is opened and set as output file descriptor (using dup2)
i == 3: *recursion and setup pipe*
// in the recursive call commands[0] is "sort"
(recursion) i == 0: set program name
(recursion) i == 1: append argument "--rev"
(recursion) i == 2: exit function because commands[i] == NULL

第二种方式:使用管道作为分隔符分割每个命令

command_t *parse_sequence(char *sequence)
{
    command_t *ret = malloc(sizeof(command_t));
    command_t current_command = ret;
    char **tokens = split_tokens(sequence, (char **){"|", NULL});
    int i = 0;

    while (commands[i]) {
        if (!strcmp(commands[i], "<")) {
            // set input file (open commands[++i])
        }
        if (!strcmp(commands[i], ">")) {
            // set output file (open commands[++i])
        }
        if (!strcmp(commands[i], "|") // tokens are kept when splitting
            // setup pipe
            // current_command = current_command->next
            // i++
        else {
            if (i > 0 && commands[i - 1] pipe or redirection)
                // set program name
            else
                // append args 
        }

    }
    return (ret);
}

示例ls > file | sort --rev

i == 0: ls is set as program_name
i == 1: ++i (file) is opened and set as output file descriptor (using dup2)
i == 3: *setup pipe* and current_command = current_command->next
i == 4: set program name
i == 5: append argument "--rev"
i == 6: exit function because commands[i] == NULL

两种方法中哪一种是最好的? 我会遇到什么问题?

我知道我的示例在tcsh中是错误的,但这对我的问题并不重要

我的时间很少,所以我想要最快的实施方式

谢谢!

0 个答案:

没有答案