【问题标题】:String formatting without index in python2.6python2.6中没有索引的字符串格式
【发布时间】:2013-12-29 17:19:12
【问题描述】:

我有成千上万行具有 python2.7+ 样式字符串格式的 Python 代码(例如,{}s 中没有索引)

"{} {}".format('foo', 'bar')

我需要在python2.6下运行这段代码,需要索引。

我想知道是否有人知道允许 python2.6 运行此代码的无痛方式。如果有一个from __future__ import blah 解决这个问题,那就太好了。我没有看到一个。类似的东西将是我的第一选择。

一个遥远的第二个将是一些可以自动化添加索引过程的脚本,至少在明显的情况下:

"{0} {1}".format('foo', 'bar')

【问题讨论】:

  • 可能不是一个实际的解决方案,但可以尝试对str 上的format 方法进行猴子修补,该方法将{} 替换为{index},然后调用'真实的'format 与添加的索引。
  • @akaIDIOT:我不认为这有两个原因。首先,TypeError: can't set attributes of built-in/extension type 'str'。其次,这不会影响字符串文字,它实际上并不调用str
  • 可以在机器上安装 Python 2.7 吗?有一些 Python 发行版可以在没有 root 权限的情况下安装和运行......
  • 使用过时版本的 python 的任何可能原因?

标签: python string-formatting python-2.6 backport


【解决方案1】:

它并没有完全保留空白,可能会变得更智能,但它至少可以正确识别 Python 字符串(撇号/引号/多行),而无需借助正则表达式或外部解析器:

import tokenize
from itertools import count
import re

with open('your_file') as fin:
    output = []
    tokens = tokenize.generate_tokens(fin.readline)
    for num, val in (token[:2] for token in tokens):
        if num == tokenize.STRING:
            val = re.sub('{}', lambda L, c=count(): '{{{0}}}'.format(next(c)), val)
        output.append((num, val))

print tokenize.untokenize(output) # write to file instead...

示例输入:

s = "{} {}".format('foo', 'bar')
if something:
    do_something('{} {} {}'.format(1, 2, 3))

示例输出(注意有点不确定的空白):

s ="{0} {1}".format ('foo','bar')
if something :
    do_something ('{0} {1} {2}'.format (1 ,2 ,3 ))

【讨论】:

  • 谢谢大家。我别无选择,只能保持 2.6 的兼容性。否则我需要升级。 tokenize 绝对是我一直在寻找的魔法。
【解决方案2】:

您可以定义一个函数来重新格式化您的格式字符串:

def reformat(s):
    return "".join("".join((x, str(i), "}")) 
                   for i, x in list(enumerate(s.split("}")))[:-1])

【讨论】:

    【解决方案3】:

    也许是一个很好的旧 sed 正则表达式,例如:

    sed source.py -e 's/{}/%s/g; s/\.format(/ % (/'
    

    您的示例将更改为:

    "%s %s" % ('foo', 'bar')
    

    授予您花哨的新样式.format(),但恕我直言,它对于微不足道的价值插入几乎没有用处。

    【讨论】:

      【解决方案4】:

      转换脚本可能非常简单。您可以找到用正则表达式替换的字符串:

      fmt = "['\"][^'\"]*{}.*?['\"]\.format"
      
      str1 = "x; '{} {}'.format(['foo', 'bar'])"
      str2 = "This is a function; 'First is {}, second is {}'.format(['x1', 'x2']); some more code"
      str3 = 'This doesn't have anything but a format. format(x)'
      str4 = "This has an old-style format; '{0} {1}'.format(['some', 'list'])"
      str5 = "'{0}'.format(1); '{} {}'.format(['x', 'y'])"
      
      def add_format_indices(instr):
          text = instr.group(0)
          i = 0
          while '{}' in text:
              text = text.replace('{}', '{%d}'%i, 1)
              i = i+1
          return text
      
      def reformat_text(text):
          return re.sub(fmt, add_format_indices, text)
      
      reformat_text(str1)
      "x; '{0} {1}'.format(['foo', 'bar'])"
      reformat_text(str2)
      "This is a function; 'First is {0}, second is {1}'.format(['x1', 'x2']); some more code"
      reformat_text(str3)
      "This doesn't have anything but a format. format(x)"
      reformat_text(str4)
      "This has an old-style format; '{0} {1}'.format(['some', 'list'])"
      reformat_text(str5)
      "'{0}'.format(1); '{0} {1}'.format(['x', 'y'])"
      

      我认为你可以通过它抛出整个文件。您可能可以找到更快的 add_format_indices 实现,显然它还没有经过大量测试。

      太糟糕了,没有import __past__,但通常这不是通常提供的东西(请参阅 2to3 脚本以获取示例),因此这可能是您的下一个最佳选择。

      【讨论】:

        猜你喜欢
        • 2019-06-10
        • 2019-02-24
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-25
        相关资源
        最近更新 更多