我正在用Python制作自己的shell,并试图使其尽可能用户友好和可自定义。不过,我在解析命令行字符串时遇到了一个问题。
我有一个要传递给命令的参数列表。
当我尝试时:
echo "Hello World!"
我的隐语是这样的:
['Hello World!', 'World!"']
而不是这个(期望的输出(:
['Hello World!']
这个问题不是错误,只是代码中的错误。
这是我的命令解析器(如果你向它传递一些东西,它应该可以自己工作(:
import os
import imp
from rich.console import Console
def handle_command(console: Console, command: str):
split_string = command.split(" ")
command_name = split_string[0]
command_name = command_name.lower()
if command_name == "":
return True
args = []
for i in range(1, len(split_string)):
if split_string[i].startswith('"'):
res = ""
pos = i
while pos <= len(split_string):
try:
res += f"{split_string[pos]} "
except IndexError:
console.print(f"[bold bright_red]ERR: Unterminated string in command arguments[/bold bright_red]")
return False
if split_string[pos].endswith('"'):
break
pos += 1
if pos == len(split_string):
if not split_string[pos].endswith('"'):
console.print(f"[bold bright_red]ERR: Unterminated string in command arguments[/bold bright_red]")
return False
res = res.replace('"', "")
args.append(res)
continue
args.append(split_string[i])
commands_dir = os.path.join(os.getcwd(), "shells/Fresh/commands")
if os.path.exists(commands_dir) and os.path.isdir(commands_dir):
for f in os.listdir(commands_dir):
if os.path.isfile(os.path.join(commands_dir, f)):
#try:
cmd = imp.load_source(command_name, os.path.join(commands_dir, f))
if cmd.name == command_name:
if cmd.min_args <= len(args):
if cmd.max_args >= len(args):
cmd.run(console, args)
return True
else:
console.print(f"[bold bright_red]ERR: {command_name} takes a maximum of {cmd.max_args} arguments[/bold bright_red]")
return False
else:
console.print(f"[bold bright_red]ERR: {command_name} requires atleast {cmd.min_args} argument[/bold bright_red]")
return False
#except Exception as e:
#console.print(f"[bold red]ERR: An error occured while running this command[/bold red]")
#return False
console.print(f"[bold bright_red]ERR: Invalid or unkown command '{command_name}'[/bold bright_red]")
return False
else:
raise FileNotFoundError("Commands directory is corrupted or does not exist")
在您的示例中,
split_string = ["echo", '"Hello', 'World!"']
因此:
for i in range(1, len(split_string)):
将执行2次(一次用于Hello,一次用于World(
它将首先将Hello world!
添加到参数中,而不是continue
,这一次将添加"World"'因为它不适合
if split_string[i].startswith('"')
我认为这里的问题主要在于令牌的解释方式。通常,当命令包含字符串时,仅用空格分割字符串是不足以正确解析命令的
我认为你应该看看什么是Lexer
您正在使用split_string = command.split(" ")
拆分命令,因此您将获得三项['echo', '"Hello', 'World!"']
。
从索引1for i in range(1, len(split_string)):
开始迭代。
您的代码通过并正确解析"Hello World!",但问题是在while循环之后添加此行args.append(split_string[i])
。
因此,它将把'World!"'
附加到结果中,因为if split_string[i].startswith('"'):
将返回False
。