【问题标题】:columns using string formatting python使用字符串格式化python的列
【发布时间】:2020-08-30 02:51:22
【问题描述】:

我正在尝试使用以下列在 bash 中复制 ls 函数:

我尝试 .format 为文件名添加填充,但我仍然没有得到所需的输出 最后一列每次都会溢出。

def show_dirs():
    filelist = os.listdir(os.getcwd())
    filelist.sort()

    scr_width = int(os.popen("stty size", "r").read().split()[1])
    max_len = -1
    for file_len in filelist:
        if len(file_len) > max_len and scr_width > max_len*2:
            max_len = len(file_len)
            mlen = max_len #+ 1

    print(color["cyan"] + "Files in the current directory")

    if scr_width < mlen:
        mlen = scr_width

    line = ""
    for count, _file in enumerate(filelist):
        if os.path.isdir(_file):
            _file = _file + os.sep
            st = "[{0:>2}] {1:<{mlen}}".format(str(count + 1), _file, mlen=mlen)
            if len(line) % scr_width > len(st):
                line = line + color["green"] + st
            else:
                line = line + "\n" + color["green"] + st
        else:
            st = "[{0:>2}] {1:<{mlen}}".format(str(count + 1), _file, mlen=mlen)
            if len(line) % scr_width > len(st):
                line = line + color["cyan"] + st
            else:
                line = line + "\n" + color["cyan"] + st
    print(line)

我得到这个输出:

【问题讨论】:

  • 我觉得这个问题很有趣。除了蛮力之外,我想不出一种好的方法来确定在给定宽度的屏幕上可以容纳多少列文本。即使确定这个数字的上限也很困难,因为可能存在不适合N 列但适合N+1 的输入列表。

标签: python python-3.x string bash


【解决方案1】:

所以,事实证明,任意字符串列表的列输出是由the Linux column command 完成的。一种选择是假设您的系统上存在此命令(它存在于我的环境中)并将其用作进程外输出过滤器。

另一种选择是深入挖掘columns 的源代码,并在 Python 中重新实现它,可能作为生成器函数。我找到了一个指针in GitHub。请注意,这是超过 800 行的 C 代码。

您还可以为该 C 代码的核心功能创建 Python 绑定,这将产生性能更好的代码。遗憾的是,我没有将 C 代码集成到 Python 中的经验。

如果您决定选择第二种选择,您可以在此处发布您的实现作为答案。

【讨论】:

  • 我查看了列命令的源代码,但它太复杂了
  • 我想出了一个解决方案,但它仅在终端大小不变的情况下才有效,因此我正在考虑创建一个函数,如果终端大小发生变化,则使用新列刷新屏幕跨度>
  • @AakashSingh - 不要让您的算法使用固定的列宽(我根据您的输出说明这一点),而 Linux 列(或 ls)算法仅使用与最宽元素一样宽的列 在列中。所以,你正在实施的不是你所说的你想要的。
  • 是的,我知道,但很难暗示我想过使用嵌套列表,但我没有办法获得最宽元素的大小,因为列可能会根据最宽元素而变化
【解决方案2】:

我改进了我的算法,现在当终端大小固定时它可以正常工作

color = {
    "red": "\033[31m",
    "green": "\033[32m",
    "orange": "\033[33m",
    "purple": "\033[35m",
    "cyan": "\033[36m",
    "yellow": "\033[93m",
}


def show_dirs(path=os.getcwd()):
    print(color["cyan"] + "Files in the current directory")
    filelist = os.listdir(path)
    filelist.sort()

    #index padding
    ind = len(filelist)
    if ind >= 1000:
        ind = 4
    elif ind >= 100:
        ind = 3
    elif ind >= 10:
        ind = 2
    else:
        ind = 1

    scr_width = int(os.get_terminal_size()[0]) #terminal width
    mlen = max(len(word) for word in filelist) + 1 #column width
    cols = scr_width // mlen #possible columns

    if scr_width < mlen:
        mlen = scr_width

    line = ""
    lst = []
    for count, _file in enumerate(filelist, start=1):
        if os.path.isdir(_file):
            _file = _file + os.sep
            st = "[{0:>{ind}}] {1:<{mlen}}".format(
                str(count), _file, mlen=mlen, ind=ind
            )
            if scr_width - ((len(line) - cols * 5) % scr_width) > len(st): # - cols * 5 to compensate the length of color codes
                line = line + color["cyan"] + st
            else:
                lst.append(line)
                line = color["cyan"] + st

        else:
            st = "[{0:>{ind}}] {1:<{mlen}}".format(
                str(count), _file, mlen=mlen, ind=ind
            )
            if scr_width - ((len(line) - cols * 5) % scr_width) > len(st): # - cols * 5 to compensate the length of color codes
                line = line + color["green"] + st
            else:
                lst.append(line)
                line = color["green"] + st
    if lst == []:
        lst.append(line)
    print("\n".join(lst))

输出:

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2019-11-28
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多