当前位置: 首页 > 科技观察

用Python创建你自己的Shell

时间:2023-03-17 23:27:57 科技观察

介绍很多人讨厌bash脚本。每当我想做最简单的事情时,我都必须查阅文档。如何将函数的参数转发给子命令?如何将字符串分配给变量,然后将该字符串作为命令调用?如何检查两个字符串变量是否相等?如何拆分字符串并获得后半部分?etc.不是我找不到这些答案,而是我每次都得去查。然而,我们不能否认整个程序作为纯函数运行的能力,以及将一个程序的输出传递给另一个程序是多么自然。所以,我想知道,我们可以将bash的一些特性与Python结合起来吗?基础让我们从一个类开始。这是一个简单的方法,将其初始化参数保存到局部变量,然后使用subprocess.run延迟评估自身并保存结果。importsubprocessclassPipePy:def__init__(self,*args):self._args=argsself._result=Nonedef_evaluate(self):ifself._resultisnotNone:returnself._result=subprocess.run(self._args,capture_output=True,text=True)@propertydefreturncode(self):self._evaluate()returnsself._result.returncode@propertydefstdout(self):self._evaluate()returnsself._result.stdoutdef__str__(self):returnsself.stdout@propertydefstderr(self):self._evaluate()returnsself._result.stderr我们让它旋转:ls=PipePy('ls')ls_l=PipePy('ls','-l')print(ls)#<<'files.txt'print(grep('main')<'files.txt')#<<>'files.txt'print(cat('files.txt'))#<<>>ls=PipePy('ls')>>>lsfiles.txtmain.pytags我们的实例是惰性的,这意味着如果我们是对他们的结果感兴趣,他们将被评估,之后不会再做更多的事情。如果我们只是想确保操作已执行怎么办?例如,假设我们有以下脚本:frompipepyimportPipePytar=PipePy('tar')tar('-xf','some_archive.tar')print("Fileextracted")这个脚本实际上不会做任何事情,因为tar调用实际上不是评估。我认为一个好的约定是如果调用__call__时不带参数就强制求值:**kwargs}-returnself.__class__(*args,_pipe_input_pipe_input=_pipe_input,**kwargs)+result=self.__class__(*args,_pipe_input_pipe_input=_pipe_input,**kwargs)+ifnotargsandnot_pipewuval_inputs+notargsandnot_pipewuval_inputand:+return时脚本,如果你想确保命令确实被调用,你必须用一对括号调用它:frompipepyimportPipePytar=PipePy('tar')-tar('-xf','some_archive.tar')+tar('-xf','some_archive.tar')()print("Fileextracted")但是,我们还没有解决问题。考虑:date=PipePy('date')date#<<