本文我们将介绍spawn类的基本方法expect方法,这个方法是用来匹配返回的结果,这个返回的结果是指子程序的返回结果,同时会将匹配的相关信息保存在spawn类的相关属性中。
基本属性包括三个,第一个是before,是匹配点之前的文本,这里的匹配是指用expect这个方法来匹配的结果,那么匹配点之前的文本会放到before,这个实例属性中,并且我们要注意多次匹配时,不包括上次已匹配之前的内容。第二个after,它是用来保存匹配成功的内容,也是同样的是expect这个方法在进行匹配时,匹配成功的内容会放在after当中。第三个基本属性match,是用来保存已匹配的匹配对象,如果匹配不成功的话,就是none。
特殊的匹配是指pexpect库当中一个的EOF,和TIMEOUT,这两个实际上是两个异常类,它们也可以用于在expect中进行匹配,另外我们再来看expect方法的使用方式,这个方法主要的参数包含pattern和timeout,从这个名称上可以看出来,timeout实际上就是超时的,pattern就是用于匹配的主要模式,对于这个可以是以下几种形式,可以为字符串,正则表达式,EOF,TIMEOUT,或者是以上类型的列表。用以匹配子命令返回的结果。从子命令返回结果中进行匹配,若只提供字符串等非列表,匹配成功返回0,若提供列表,则返回匹配成功的列表序号,匹配失败,则会引发异常。
下面我们来看expect匹配方法的使用事例,首先启动虚拟机,进入python3,然后导入这个模块,首先我们要建立一个spawn事例,这个时候我们运行的是pexpect这个命令,列出当前目录下的目录以及文件,建立了spawn事例以后,我们就可以调用expect的方法来进行匹配。
比如我们当前的目录下面有test这个文件,那么就可以尝试来匹配test。 直接调用这个类实例的expect方法。
传递给他一个参数喂test,也就是之前的pattern参数,给它的值为test,然后从“ls -l”这个命令中来匹配test这个信息,那么返回值为0,表示匹配成功,如果我们要查询要匹配的结果,就可以使用spawn类的before属性或者after属性来查看,首先用before属性,输命令后出来的都是匹配以前的内容。那么匹配到什么信息,我们可以用after来查看,我们还可以通过调用它的match属性来查看匹配的结果,也就是正则对象,这个正则对象显示了接到的信息是从289到293。匹配的内容就是test,对于子程序返回的信息,我们还可以进行多次匹配。
我们匹配到的test实际上在这个test后面ttt文件,我们也可以来匹配ttt,这个时候我们传入一个列表形式的参数。可以看到它返回的值为1,也就是说test已经匹配过了,它不会子程序返回信息的开头再次去匹配,而是从子程序匹配完之后的信息当中,进行匹配,所以它匹配到的是tt。
我们也可以用before属性来进行查看,那么这是匹配之前的内容,匹配之前的内容当然不包括之前已经被匹配的内容,我们还可以同样的看到它的after,可以看到tt被匹配到了,当执行的匹配没有匹配成功的时候,它会抛出异常,比如我们刚刚的test,已经匹配完成了,如果我要再次匹配test。
可以看到这个系统就输出了很多内容,就表示此时已经抛出了异常,也就是没有匹配到内容。
这里的expect方法对pattern进行匹配,有一些和我们平常常用的正则表达式的匹配方式是有所不同的,因为它的匹配方式是从返回的信息中逐个字符读出,然后进行匹配,当pattern为列表的时候,从左至右哪个最先匹配到就匹配哪个。
比如说我们仍然来做pexpect的匹配,然后我们来做这样一个匹配,输入代码,可以看到匹配的结果为1,也就是te被匹配到了,但是tt没有被匹配到,那么tt在我们刚刚列出的信息当中实际上是包含tt的,也包含了te,而且tt在te的后面,而在匹配的时候,因为它是被输出的信息从前到后进行匹配的,所以在列表当中的te被首先匹配到,因此它返回的1,而不是返回0。也就是说第二个先出现的字符串被匹配到,而第一个没有被匹配,这就是列表的匹配顺序。
对于列表的匹配,我们还可以这样使用,比如,当我们在匹配结果信息的时候,如果不存在这个结果信息,那么程序就会抛出异常,中断运行,因此,我们还可以在列表中添加一个EOF这个项目,来使得匹配的时候不会退出程序。
下面我们来看一个简单的例子,首先我们仍然先启动一个子程序, 由于这里面的命令只会输出当前命令下的所有文件和目录,如果我们要随意指定一个名称,可能它就会中断程序的执行,所以我们在匹配的时候,可以这样来做,输入命令后面加上EOF,这样我们就可以知道返回的结果,知道这个命令是否能够成功。由于这个abc是匹配不成功的,所以它匹配的就是第二个项目,所以返回的是1,因此这个程序并不会中断执行。如果我们要直接匹配abc,可以看到会匹配失败,程序会中断执行,这是列表的另外一种用法。
在expect方法中进行匹配的时候,会自动应用re.DOTALL正则选项里面的“.+”可以匹配所有字符,“.*”返回空字符。如果在expect方法中,要匹配行尾,我们需要使用“r/n”,这个字符串,如果在正则表达式中使用“$”符号来匹配行尾,下面我们具体来看实例。
首先我们要先看换行符的实例。
我们运行的命令仍然是ls-l命令,匹配一个换行,用“/r/n”来表示,然后返回0表示匹配成功,我们可以查看匹配的结果,这就是匹配之前的内容,这个就是匹配到的换行符,我们还可以查看匹配的整个字符串,这是匹配行的方法,如果我们使用“.*”来进行匹配的话,对于返回信息的第一次匹配,“.*”号会返回一个控制符。
输入代码进行匹配,匹配完成之后我们在进行“.*”的匹配,然后查看一下匹配的结果,可以看到它将剩下的所有的字符的结果全部匹配进去了,这就是“.*”用来匹配的特殊的情况,也就是在开始匹配和后天的匹配,结果是不同的。
我们可以看到spawn这个类,它启动的子程序返回信息after类型,所以我们如果要匹配这里面的返回信息中的中文字符串,我们就需要把中文字符串进行编码,比如在这个桌面当中,有“公共”这个字符串,我们来匹配它,来查看一下。
首先我们仍然先建立实例,进行ls这个命令,然后我们来匹配一下它的中文,掉用“encode”这个方法,用utf8来进行编码,然后查看匹配的结果,那么它就是一个字符串的形式,如果我们要看它真正的值,然后我们可以先将它进行解码,可以看到它就是“公共”这两个字,也就是说我们在这个地方进行中文匹配的时候,要对中文进行编码。
来源:麦子学院