通过pexpect发送命令时如何避免冗余?

How to avoid redundancy when sending commands via pexpect?

我有一个 python 的预期代码,它发送文件中列出的一些命令。

假设我将一些命令存储在名为 commandbase

的文件中
ls -l /dev/
ls -l /home/ramana
ls -l /home/ramana/xyz
ls -l /home/ramana/xxx
ls -l /home/ramana/xyz/abc
ls -l /home/ramana/xxx/def
ls -l /home/dir/

等等。

请注意,在 / 之后,我将 devhome 作为变量。如果我再次进入 home ramanadir 作为变量。如果进入ramana,则又是xyzxxx。所以基本上它的形式是

ls -l /variable1/variable2/variable3/ 

等等。这里我需要为每个变量及其特定的二级变量构建一棵树。

现在我应该有一个 list/array/file,我将在另一个列表中存储第一个变量及其次要变量,依此类推。

所以我需要这样的功能

在主脚本中

for line in database:
             child.sendline(line+"\r")
             child.expect("$",timeout)

数据库文件应该是这样的:

 def commands():
        return "ls -l <some variable>/<second variable and so on>"

这个函数应该return所有命令与所有组合

如何在此处 return 变量命令而不是定义所有命令?数组或列表可以吗?

[EDIT] 编辑,因为不太清楚。希望这次我清楚了

这可以通过列表理解来完成...

paths = ['/dev/', '/dev/ramana/', ...]
command = 'ls -l'
commandsandpaths = [command + ' ' + x for x in paths]

commandsandpaths 将是一个列表...

ls -l /dev/
ls -l /dev/ramana/

就个人而言,我更喜欢使用字符串格式化而不是字符串连接...

commandsandpaths = ['{0} {1}'.format(command, x) for x in paths]

但如果您不熟悉语法,它的可读性可能会降低

您的要求比乍看起来要复杂一些。下面我采用了一种约定,使用列表 [...] 来表示要连接的东西,并使用元组 (...) 来表示可供选择的东西,即可选值。

您的路径名列表现在可以表示为:-

database = (
    'dev',
    ['home', (
            'dir',
            ['ramana', (
                    '',
                    ['xyz', (
                            '',
                            'abc'
                        )
                    ],
                    ['xxx', (
                            '',
                            'def'
                        )
                    ]
                   )
            ]
         )
    ]
)

以上语法尽量避免冗余。空格不是必需的,但有助于说明哪些部分处于同一嵌套级别。

接下来我们需要一种方法将其转换为命令列表:-

def permute(prefix, tree):
    def flatten(branch):
        #print 'flatten', branch
        results = [ ]
        if type(branch) is list:
            parts = [ ]
            for part in branch:
                if type(part) is basestring:
                    if part:
                        parts.append([part])
                else:
                    parts.append(flatten(part))

            index = map(lambda x: 0, parts)
            count = map(len, parts)
            #print 'combining', parts, index, count
            while True:
                line = map(lambda i: parts[i][index[i]],
                       range(len(parts)))
                line = '/'.join(line)
                #print '1:', line
                results.append( line )
                curIndex = len(parts)-1
                while curIndex >= 0:
                    index[curIndex] += 1
                    if index[curIndex] < count[curIndex]:
                        break
                    index[curIndex] = 0
                    curIndex -= 1
                if curIndex < 0:
                    break
        elif type(branch) is tuple:
            for option in branch:
                if type(option) is basestring:
                    if len(option):
                        #print '2:', option
                        results.append( option )
                else:
                    results.extend(flatten(option))
        else:
            #print '3:', branch
            results.append( branch )
        return results

    return map(lambda x: prefix + x, flatten(tree))

所以现在如果我们调用 permute('ls -l /', database) 它 returns 以下列表:-

[
    'ls -l /dev', 
    'ls -l /home/dir', 
    'ls -l /home/ramana/', 
    'ls -l /home/ramana/xyz/', 
    'ls -l /home/ramana/xyz/abc', 
    'ls -l /home/ramana/xxx/', 
    'ls -l /home/ramana/xxx/def'
]

从这里开始,将这些字符串写入名为 commandbase 的文件或逐行执行文件变得很简单。

不确定你所说的这些变量是什么。它们对我来说就像路径段。

假设您有一个由节点组成的树数据结构,其中每个节点都是路径段的元组和子树列表:

tree = [
    ('dev', []),
    ('home', [
        ('ramana', [
            ('xyz', [
                ('abc', []),
            ]),
            ('xxx', [
                ('def', []),
            ]),
        ]),
        ('dir', []),
    ]),
]

你可以写一个递归生成器函数来遍历树生成所有路径:

import os
import os.path

def walk_tree(tree):
    for name, subtree in tree:
        yield name
        for path in walk_tree(subtree):
            yield os.path.join(name, path)

然后您可以生成所有命令:

commands = ['ls -l {path}'.format(path=os.sep + path) for path in walk_tree(tree)]

注意,这段代码不是数据库,是可以生成数据库的代码。此外,显示的代码以 depth-first 顺序遍历树,这与您显示的顺序不同(这似乎是 depth-first 和 breadth-first 的某种组合)。