Python自定义Shell命令解析Bug:带引号参数重复添加问题
自定义Shell命令解析Bug:带引号参数拆分错误
我正在用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")
问题原因及修复方案
核心问题
- 重复添加参数:用
for循环遍历拆分后的元素时,处理完引号包裹的多段内容后,没有跳过已经处理过的元素,导致后续被拼接的元素被再次单独添加到参数列表中。 - 循环边界越界:
while pos <= len(split_string)会触发IndexError,后续判断split_string[pos]也会越界访问。 - 多余空格残留:拼接引号内元素时每个部分后加空格,会导致参数末尾多出不必要的空格。
修复后的代码
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 = [] i = 1 while i < len(split_string): part = split_string[i] if part.startswith('"'): res = part[1:] # 移除开头引号 pos = i + 1 # 遍历直到找到结尾引号或元素耗尽 while pos < len(split_string): current_part = split_string[pos] if current_part.endswith('"'): res += " " + current_part[:-1] # 移除结尾引号并拼接 pos += 1 break res += " " + current_part pos += 1 else: # 未找到结尾引号,抛出错误 console.print(f"[bold bright_red]ERR: 命令参数中存在未闭合的字符串[/bold bright_red]") return False args.append(res) i = pos # 跳过已处理的元素 else: args.append(part) i += 1 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): file_path = os.path.join(commands_dir, f) if os.path.isfile(file_path): try: cmd = imp.load_source(command_name, file_path) 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} 最多接受 {cmd.max_args} 个参数[/bold bright_red]") return False else: console.print(f"[bold bright_red]ERR: {command_name} 至少需要 {cmd.min_args} 个参数[/bold bright_red]") return False except Exception as e: console.print(f"[bold red]ERR: 运行命令时发生错误[/bold red]") return False console.print(f"[bold bright_red]ERR: 无效或未知命令 '{command_name}'[/bold bright_red]") return False else: raise FileNotFoundError("命令目录损坏或不存在")
关键修复点
- 将
for循环改为while循环,手动控制索引步进,避免重复处理已拼接的元素。 - 直接移除首尾引号,避免全局替换引号导致的潜在问题(后续可扩展支持转义引号)。
- 修正循环边界,消除越界访问风险。
- 避免拼接后残留多余空格,保证参数内容准确。
内容的提问来源于stack exchange,提问作者Spooky
相关产品推荐
相关产品推荐

