简体   繁体   English

实现命令行解释器

[英]Implementing a command line interpreter

In terminal or cmd, you can write commands, in which there is a main command and then sub-commands, or arguments and stuff...like this:在终端或 cmd 中,您可以编写命令,其中有一个主命令,然后是子命令,或参数之类的……像这样:

cd Desktop\Folder
lst
Format E: /fs:FAT32

I want to create a C# console application that could execute predefined commands like this, but which could also split up main commands and sub-commands, in which some could be optional and some not.我想创建一个 C# 控制台应用程序,它可以执行这样的预定义命令,但它也可以拆分主命令和子命令,其中一些可能是可选的,一些不是。 I have tried just taking all as string and then splitting it to array and creating if(s) and switch and case s, but it looks really bad and hardly manageable.我曾尝试将所有内容作为字符串,然后将其拆分为数组并创建if(s)switchcase s,但它看起来非常糟糕且难以管理。 I'm sure that in the OS's terminal or cmd it's build in another way.我确信在操作系统的终端或 cmd 中,它是以另一种方式构建的。 Could you help me understand the basic structure of such an application?你能帮我理解这样一个应用程序的基本结构吗?

Here, have a look at this concept.在这里,看看这个概念。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SharpConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Welcome to SharpConsole. Type in a command.");

            while (true)
            {
                Console.Write("$ ");
                string command = Console.ReadLine();

                string command_main = command.Split(new char[] { ' ' }).First();
                string[] arguments = command.Split(new char[] { ' ' }).Skip(1).ToArray();
                if (lCommands.ContainsKey(command_main))
                {
                    Action<string[]> function_to_execute = null;
                    lCommands.TryGetValue(command_main, out function_to_execute);
                    function_to_execute(arguments);
                }
                else
                    Console.WriteLine("Command '" + command_main + "' not found");
            }
        }

        private static Dictionary<string, Action<string[]>> lCommands = 
            new Dictionary<string, Action<string[]>>()
            {
                { "help", HelpFunc },
                { "cp" , CopyFunc }
            };

        private static void CopyFunc(string[] obj)
        {
            if (obj.Length != 2) return;
            Console.WriteLine("Copying " + obj[0] + " to " + obj[1]);
        }

        public static void HelpFunc(string[] args)
        {
            Console.WriteLine("===== SOME MEANINGFULL HELP ==== ");
        }
    }
}

The basic idea is to generalize the idea of a command.基本思想是概括命令的思想。 We have a Dictionary , where the key is a string (the command's name), and the value you get from the dictionary is a function of type Action<string[]> .我们有一个Dictionary ,其中键是一个字符串(命令的名称),你从字典中得到的值是一个Action<string[]>类型的函数 Any function which has the signature void Function(string[]) can be used as this type.任何具有签名void Function(string[])都可以用作这种类型。 Then, you can set up this dictionary with a bunch of commands and route them to the functions you want.然后,您可以使用一堆命令设置此字典并将它们路由到您想要的功能。 Each of these functions will receive an array of optional arguments.这些函数中的每一个都将接收一组可选参数。 So here, the command "help" will be routed to the HelpFunc() .所以在这里,命令“help”将被路由到HelpFunc() And the "cp" command eg will receive an array of filenames.例如,“cp”命令将接收一个文件名数组。 The parsing of the command is always the same.命令的解析总是相同的。 We read a line, split it a space.我们读取一行,将其拆分为一个空格。 The first string is the program's name, command_main here.第一个字符串是程序的名称,这里是command_main If you skip the first string, you'll get an enumeration of all the other subcommands or switches you typed in. Then, a lookup in the dictionary is being done to see if there is such a command.如果您跳过第一个字符串,您将获得您输入的所有其他子命令或开关的枚举。然后,在字典中进行查找以查看是否有这样的命令。 If yes, we get the function and execute it with the arguments.如果是,我们获取函数并使用参数执行它。 If not, you should display "command not found" or something.如果没有,您应该显示“未找到命令”或其他内容。 All in all, this exercise can be minimized to looking up a function in a dictionary of possible command strings, then executing it.总而言之,这个练习可以最小化为在可能的命令字符串字典中查找函数,然后执行它。 So a possible output is所以可能的输出是

Welcome to SharpConsole. Type in a command. 
$ help
===== SOME MEANINGFULL HELP ==== 
$ cp file1 otherfile2 
Copying file1 to otherfile2 
$ python --version
Command 'python' not found
$ ...

LXSH LXSH

It's a command interpreter similar to CMD or Bash .它是一个类似于CMDBash的命令解释器。 We've distributed it under MIT license, a shell with some functionalities in C# (.NET Core).我们在 MIT 许可下分发了它,这是一个在 C# (.NET Core) 中具有一些功能的外壳。 You can contribute if you wish on GitHub .如果您愿意,可以在GitHub 上做出贡献

To solve the problem of matching a given token (part of the command line) with a builtin or a command, we use a dictionary.为了解决将给定标记(命令行的一部分)与内置或命令匹配的问题,我们使用字典。

However, we don't index the programs in the path for the moment.但是,我们暂时不索引路径中的程序。 We just combine the name of the program with all the paths in the %PATH% variable.我们只是将程序名称与%PATH%变量中的所有路径结合起来。

  1. Capture input捕获输入
  2. Expand environment variables, expand aliases展开环境变量,展开别名
  3. Try to match a builtin and run it if there is a match尝试匹配内置函数并在匹配时运行它
  4. Try to match with a program in %PATH% / $PATH尝试与%PATH% / $PATH的程序匹配
  5. Run the program or display error运行程序或显示错误

While you are unlikely to find the internal working of CMD (because it's closed source), you can find easily unix shell (bash, sh, zsh, etc..) information.虽然您不太可能找到 CMD 的内部工作(因为它是封闭源代码),但您可以轻松找到 unix shell(bash、sh、zsh 等)信息。

Links:链接:

Bash Reference Bash 参考
Zsh Reference Zsh 参考
TCSH Reference TCSH 参考

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

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