左截断使用python 3.5 str.format?

时间:2016-06-22 17:21:20

标签: python string python-3.x string-formatting

问:是否可以使用Python 3.5的字符串格式化语法创建格式字符串以截断?

基本上我想做的是拿一个git SHA:

"c1e33f6717b9d0125b53688d315aff9cf8dd9977"

仅使用格式字符串,只显示正确的8个字符:

"f8dd9977"

我尝试过的事情:

语法无效

>>> "{foo[-8:]}".format(foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977")
>>> "{foo[-8]}".format(foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977")  
>>> "{:8.-8}".format("c1e33f6717b9d0125b53688d315aff9cf8dd9977")

错误的结果

### Results in first 8 not last 8. 
>>> "{:8.8}".format("c1e33f6717b9d0125b53688d315aff9cf8dd9977")

有效但缺乏灵活性和繁琐

### solution requires that bar is always length of 40.
>>> bar="c1e33f6717b9d0125b53688d315aff9cf8dd9977"
>>> "{foo[32]}{foo[33]}{foo[34]}{foo[35]}{foo[36]}{foo[37]}{foo[38]}{foo[39]}".format(foo=bar)

类似的问题是asked, but never answered。然而我的不同之处在于我仅限于使用格式字符串,我没有能力改变输入参数的范围。这意味着以下是一个不可接受的解决方案:

>>> bar="c1e33f6717b9d0125b53688d315aff9cf8dd9977"
>>> "{0}".format(bar[-8:])

我应该澄清的另一个方面......上面解释了最简单的问题形式。在实际情况中,问题更准确地表达为:

>>> import os
>>> "foo {git_sha}".format(**os.environ)

我想要left_truncate“git_sha”环境变量。不可否认,这比最简单的形式更复杂,但如果我能解决最简单的问题 - 我可以找到解决更复杂问题的方法。

2 个答案:

答案 0 :(得分:1)

是否将str子类化为选项?

foo="c1e33f6717b9d0125b53688d315aff9cf8dd9977"

class CustomStr(str):
    def __format__(self, spec):
        if spec == 'trunc_left':
            return self[-8:]
        else:
            return super().__format__(spec)

s = CustomStr(foo)

print('{}'.format(s))
print('{:trunc_left}'.format(s))

从那里,你可以做一些像这样工作的事情:

import os

class CustomStr(str):
    def __format__(self, spec): 
       return self[-8:]

class OsEnvironWrapper(dict):
    def __init__(self, environ):
        self.environ = environ

    def __getitem__(self, key):
        if key == 'git_sha':
            return CustomStr(self.environ[key])
        else:
            return self.environ[key]

os_environ = OsEnvironWrapper(os.environ)
print('foo {git_sha}'.format(**os_environ))

我知道,包装器几乎不可接受,但你可以通过正确模拟容器类型来调整它是透明的。

[edit]请参阅Jim的解决方案,了解不是strdict的子类。

答案 1 :(得分:1)

所以这是我的解决方案,感谢@JacquesGaudin和#Python上的人提供了很多指导......

class MyStr(object):
    """Additional format string options."""
    def __init__(self, obj):
        super(MyStr, self).__init__()
        self.obj = obj

    def __format__(self, spec):
        if spec.startswith("ltrunc."):
            offset = int(spec[7:])
            return self.obj[offset:]
        else:
            return self.obj.__format__(spec)

这样做可行:

>>> f = {k: MyStr(v) for k, v in os.environ.items()} 
>>> "{PATH:ltrunc.-8}".format(**f)