简体   繁体   English

将字符串作为带有空格分隔的参数的命令读取的最佳方法是什么?

[英]What is the best way to read a string as a command with a whitespace separated argument?

I'm currently writing a primitive shell that lets user input few basic commands: ls , cat etc. I'm taking from the user an input like: ls /home/someUser/someDirectory and storing this in a character array, say input . 我目前正在编写一个基本的外壳程序,该外壳程序让用户输入一些基本命令: lscat等。我从用户那里获得一个输入: ls /home/someUser/someDirectory并将其存储在一个字符数组中,例如input I've written a few little such functions ls , cat etc. that take an argument and print to stdout the expected result. 我已经写了一些这样的函数lscat等,它们带有一个参数并打印以stdout预期的结果。

What I'd like to know is: what would be the best way to break this input up into a command and argument? 我想知道的是:将input分解为命令和参数的最佳方法是什么? For the said example, I'd like to get two different chunks: ls and /home/someUser/someDirectory , so that I can check what command the user wants to execute with what argument. 对于上述示例,我想获得两个不同的块: ls/home/someUser/someDirectory ,以便可以使用什么参数检查用户要执行的命令。 Sure, I can maintain pointers and check the first few characters of the array and compare them and then proceed to the character after whitespace and parse the argument accordingly, but that would be very tedious and inefficient. 当然,我可以维护指针并检查数组的前几个字符并进行比较,然后进行空格之后的字符并相应地解析参数,但这将非常繁琐且效率低下。 Is there a better way to do this, possibly an in-built function? 有没有更好的方法可以做到这一点,可能是内置功能?

Thanks in advance. 提前致谢。

You could try using strtok : 您可以尝试使用strtok

#include <string.h>
#include <stdio.h>

int main(){
  char example_input[80] = "ls /home/user/directory/file.ext";
  const char s[2] = "-";
  char *token = strtok(example_input, " ");

  /* walk through other tokens */
  while( token != NULL ){
     printf("%s\n", token );
     token = strtok(NULL, s);
  }

  return(0);
}

Escape characters will be somewhat trickier. 转义字符会有些棘手。

If you only need to divide the string into command and argument this may work: 如果只需要将字符串分为命令和参数,则可以使用:

#include <string.h>
#include <stdio.h>

void cmd_ls(const char *arg){
  printf("lsing %s\n",arg);
}

void cmd_pwd(const char *arg){
  printf("pwding %s\n",arg);
}

int main(){
  char example_input[80] = "psdwd /home/user/directory/file.ext";
  const char s[2] = "-";

  //Find command, assuming it ends at the first space

  //Points to first space in string, will eventually point to beginning of
  //command
  char *command  = strchr(example_input, ' ');

  //Will point to beginning of argument
  char *argument = NULL;

  //If command is not NULL, then there is at least one space, so the string has
  //the form "<COMMAND> X" where X is either '\0' (string terminator) or another
  //character. If the string contains a space, edit it so that there is a
  //terminator after the command. If there is an argument, return a pointer to
  //its beginning (which may be a space).
  if(command!=NULL){
    *(command) = '\0';       //Terminate command string
    if(*(command+1)!='\0')   //If there are argument characters, point to them
      argument = command+1;
  }
  command = example_input;   //Point command to beginning of command


  //Do I recognise this command?
  if(strcmp(command,"ls")==0){
    cmd_ls(argument);
  } else if(strcmp(command,"pwd")==0) {
    cmd_pwd(argument);
  } else {
    printf("Unrecognised command!\n");
  }

  return(0);
}

Check this out 看一下这个

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **split(char *const source, const char *const delimiter)
{
    size_t length;
    char **list;
    size_t count;
    char  *pointer;
    char  *token;
    void  *saved;

    if ((source == NULL) || (delimiter == NULL))
        return NULL;

    list    = NULL;
    pointer = source;
    count   = 0;
    while ((token = strtok(pointer, delimiter)) != NULL)
    {
        saved = realloc(list, (1 + count) * sizeof(*list));
        if (saved == NULL)
            goto abort;
        length      = strlen(token);
        list        = saved;
        list[count] = malloc(1 + length);
        if (list[count] == NULL)
            goto abort;
        strcpy(list[count], token);
        pointer = NULL;

        count++;
    }
    saved = realloc(list, (1 + count) * sizeof(*list));
    if (saved == NULL)
        return list;
    list        = saved;
    list[count] = NULL;

    return list;
abort:
    while (count != 0)
        free(list[count--]);
    free(list);

    return NULL;
}

int main()
{
    size_t k;
    char string[] = "example string with spaces";
    char **list;

    list = split(string, " ");
    if (list == NULL)
        return -1;
    k = 0;
    while (list[k] != NULL)
    {
        printf("%s\n", list[k]);
        free(list[k]);

        k++;
    }
    free(list);
    return 0;
}

The split function will return an array of char pointers which contain the tokens, and have a sentinel NULL pointer that tells you where the end of the list is. split函数将返回一个包含指针的char指针数组,并具有一个前哨NULL指针,该指针告诉您列表的结尾在哪里。

you can do it simply using scanf. 您可以简单地使用scanf做到这一点。 you have to read the input until you get a '\\n' character. 您必须先阅读输入内容,直到获得'\\ n'字符为止。 the code to do it will be : 要做的代码是:

scanf("%[^\n]", string);

the total string will be stored in the array string. 总字符串将存储在数组字符串中。 you can do further string processing to extract the required data. 您可以进行进一步的字符串处理以提取所需的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM