【问题标题】:Can python act like this, in bash?python可以像这样在bash中表现吗?
【发布时间】:2012-10-11 04:54:03
【问题描述】:

python可以通过这样的短格式语法生成具有多子路径的路径吗?

vars=project/{DEBIAN,usr/{bin,usr/{applications,icons,share}},computer}

【问题讨论】:

    标签: python shell path glob expansion


    【解决方案1】:

    通常我会建议使用类似的东西

    def extend(base, *others):
        [base + o for o in others] if others else [base]
    

    然后做

     extend("project", "/debian", *extend("/usr", *(extend("/bin") + extend("/usr", "/applications", "/icons", "/share"))))
    

    。但是由于您更喜欢解析字符串,因此我尝试提供一种替代方法:

    def commasplit(s):
        start = 0
        level = 0
        for i, c in enumerate(s):
            if c == '{':
                level += 1
            elif c == '}':
                level -= 1
            elif c == ',' and level == 0:
                yield s[start:i]
                start = i+1
        yield s[start:]
    
    def split(s):
        import re
        found = False
        for m in re.finditer("(\{.*\})",s):
            found = True
            for p in commasplit(s[m.start() + 1:m.end() - 1]):
                for i in split(p):
                    yield s[:m.start()] + i + s[m.end():]
        if not found:
            yield s
    
    cs = "a,b,c,{d,e,f},g"
    print list(commasplit(cs)) # -> seems to work
    
    s = "project/{DEBIAN,usr/{bin,usr/{applications,icons,share}},computer}"
    print s
    for n, i in enumerate(split(s)): print n, i # ->  as well.
    

    【讨论】:

    • >>> print list(commasplit(cs)) # -> 似乎有效 ['a', 'b', 'c', '{d,e,f}' , 'g']
    • @UhBaUnTaUh 没错。它故意只在第一级工作。 split() 递归调用自己,所以最后一切都应该是正确的。
    • 你让我对 yield 和 enumerate 有了更多的了解,我熟悉了正常的 return 让我有一些糟糕的编程习惯。此外,您的代码让我想起了解释器/编译器编程。谢谢。
    • 对不起,我是这种编码风格的新手。我试图阅读您的代码以将其修改为我想要的方式,但是我不了解 iter 的概念,所以我不知道如何修改它。你能帮我把你的代码修改成这种风格吗? pythonGenPath("project,[DEBIAN,usr,[bin,usr,[applications,icons,share/winpath]],computer]")
    • 我认为这将是创建不带双引号的列表的有用方法。我想修改它以生成多维双引号字符串列表。
    【解决方案2】:

    不,没有这样的内置速记。一个合理的pythonic方式是:

    vars = ["project" + path for path in (
        ["/DEBIAN"] +
        ["/usr" + path for path in (
            ['/bin'] +
            ['/usr' +  path for path in [
                "/applications",
                "/icons",
                "/share"]
            ]
        )] +
        ['/computer']
    )]
    

    编辑:

    您可以定义一个函数来简化此操作。这是一个惰性生成器版本:

    def expand(base, paths):
        for path in paths:
            if type(path) == str:
                yield base + path
            else:
                for p in path:
                    yield base + p
    
    vars = expand("project", [
        "/debian",
        expand("/usr", [
            "/bin",
            expand("/usr", [
                "/applications",
                "/icons",
                "/share"
            ]),
            "/computer"
        ])
    ])
    

    【讨论】:

    • 如果您愿意,可以采用字符串解析方法。我认为这是在单个语句中做到这一点的最佳方式
    【解决方案3】:

    谢谢。

    我尝试编写我的代码。

    我总是使用 ["0,1,2,3,4,5,6,7,8,9".split(","),["a,b,c,d,e".split (",")]] 而不是普通的列表。

    因为它比 ["x","y","z"] 更快 - 无需换档,清楚且更有意义。

    所以,我希望很快会有一些字符串方法可以像bash,下面的代码,在python中,很快......

    Python 语法:project,[DEBIAN,usr,[bin,usr,[applications,icons,share/winpath]],computer]

    Bash 语法:project/{DEBIAN,usr/{bin,usr/{applications,icons,share}},computer}

    import re
    def genpaths (multils, root=""):
        suc=[]
        for l in multils:
            if type(l) == type([]):
                suc.extend(genpaths (l, root+multils[multils.index(l)-1]+"/"))
            else: 
                suc.append( root+l)
        return filter(None, suc)
    
    def easylist (s):
        s=eval("['''"+re.sub("(\]+)(''',''')?", "'''\\1,'''",re.sub("(''',''')?(\[+)","''',\\2'''",re.sub(",","''','''",s)))+"''']")
        return s
    
    def bashlist (s):
        s=eval("['''"+re.sub("(\}+)(''',''')?", "'''\\1,'''",re.sub("(/)?(\{+)","''',\\2'''",re.sub(",","''','''",s))).replace("{","[").replace("}","]")+"''']")
        return s
    
    def pythonGenPath (s):
        return genpaths(bashlist (s))
    
    def bashGenPath (s):
        return genpaths(bashlist (s))
    
    #testing
    print pythonGenPath ("project,[DEBIAN,usr,[bin,usr,[applications,icons,share/winpath]],computer]")
    print bashGenPath ("project/{DEBIAN,usr/{bin,usr/{applications,icons,share}},computer}")
    

    结果是:

    ['project', 'project/DEBIAN', 'project/usr', 'project/usr/bin', 'project/usr/usr', 'project/usr/usr/applications', 'project/usr/usr/icons', 'project/usr/usr/share', 'project/computer']
    

    【讨论】:

    • 你的代码很臭,因为它无缘无故地使用了eval()。我尝试改进它...
    • ^.^ 对不起。我懒得定义循环和函数,而且我的编程知识和我的英语技能一样糟糕。我只是使用这段代码来构建我的 debian 包项目。不过,我希望有人能给我们更多更高级的漂亮代码。谢谢你。 ;D
    猜你喜欢
    • 2014-09-10
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多