2011-06-11 55 views
0

我想格式化文本内容,我使用column作为标准输出流,但是我失败了。例如,使用一个单一的线,一切工作正常:Linux:使用列格式化流(管道)输出? (未确定的文件大小)

$ echo "1 12 123 1234 1 12 123 1234 " | column -t 
1 12 123 1234 1 12 123 1234 

。但是,如果我尝试模拟“没完没了”流:

$ while true; do echo "1 12 123 1234 1 12 123 1234 "; sleep 1; done | column -t 
^C 

...根本就没有反应,直到用Ctrl-C退出。

(注意while事情是只是为了模拟从设备读取层出不穷,如“cat /dev/ttyUSB0”)

这使我相信,即使column默认情况下应该接受标准输入,它需要一个“完整的”和完成的文件(即,具有确定的文件大小)才能工作;而在“无尽的”流的情况下,情况并非如此 - 所以它从不输出任何东西。

任何有关如何在此上下文中实现列格式的建议?编辑:不一定必须是column程序;任何其他格式文本成列将罚款(但我恐怕,例如awk也需要一个完整的文件)...

在此先感谢,
干杯!

+3

最有可能列有阅读所有的输入,以决定如何广,使每一列。所以你不能将它用于“无尽的”流,否则它最终会消耗所有的内存。 – Keith 2011-06-11 15:58:28

+0

感谢您确认@Keith - 我猜是这样,'column'不适用于此;但那里是否存在替代工具,这将工作“每行”而不是“每个文件”?我想,在这种情况下,列数和列宽必须事先指定,但这对我来说是可以的。干杯! – sdaau 2011-06-11 16:02:31

+2

您可以将其管道化为sed,并用制表符替换空格,并让终端制表符将其格式化为列。 '... | sed -e's/[] \ +/\ t/g'' – Keith 2011-06-11 16:13:47

回答

1

我也发现列无法流式传输令人失望,而sdaau的代码无法测量我的列。所以这是对这两个问题的解决方法。无论如何,这可能不是非常有效,但它只是用于调试。我有它在我的pcol〜/ bin文件夹(一定要使用chmod + X吧):

#!/usr/bin/env python 
import sys 

sep = ',' 
gutter = 2 
for arg in sys.argv: 
    if arg.startswith('-s'): 
     sep = arg[2:] 
    elif arg.startswith('-g'): 
     gutter = int(arg[2:]) 

widths = [] 
while True: 
    raw = sys.stdin.readline() 
    line = raw.strip('\0').strip('\n') 
    vals = line.split(sep) 
    if len(vals) > len(widths): 
     widths = [0] * len(vals) 

    widths = [max(len(val) + gutter, width) for val, width in zip(vals, widths)] 
    metaformat = '%%%ds' * len(widths) 
    format = metaformat % tuple(widths) 
    print format % tuple(vals) 
+0

非常感谢你,@chbrown - 只是试过“'while true; do let”k = $ RANDOM%800“; echo”1 12 $ k 1234 1 12 123 $ RANDOM“; sleep 1; done | python pcol .py -s''-g3'“,它的工作原理很好:)移动也接受;再次感谢 - 欢呼! – sdaau 2012-04-19 17:24:15

1

没有响应,因为你的第二个命令创建了一个无限循环,然后询问完成后,结果被传送到列-t。由于循环永远不会终止,因此列-t不会执行任何操作。我不知道你想实现什么,但第二个命令,做每隔一秒产生输出(这是你想要什么我假设)的变化是这样的:

while true; do echo "1 12 123 1234 1 12 123 1234 " | column -t; sleep 1; done 

编辑: 我现在看到你在做什么。对于你的情况,你可以用sed来替换选项卡上的空间,这将自动只要调整您的号码上一个上线的位数不超过标签尺寸:

echo "1 12 123 1234 1 12 123 1234 " | sed 's/ /\t/g' 
+0

Hi @ user507078 - 谢谢你,但我正在使用'while'构造来模拟无尽的流,就像在从设备中读取数据流一样,在'cat/dev/ttyUSB0'中 - 数据每秒出现一次。 .. – sdaau 2011-06-11 15:53:46

0

OK,感谢响应在这里,我设法制作了一个能够做到这一点的python脚本;显然,你必须知道(并输入脚本)列的格式先验;这里的脚本,columnizeline.py

#!/usr/bin/env python 

import sys; 

#below no work: 
#print sys.stdin; 
#for line in sys.stdin: 
# sline=line.split(' ') 
# print sline 

while 1: 
    next = sys.stdin.readline() 
    ns = next.strip('\0').split(' ') # remove null char 
    ns.pop() # remove the last entry in the list, it is '\n' 
    #~ nextf = "%4s %4s %4s %4s %4s %4s %4s %4s" % (ns[0], ns[1], ns[2], ns[3], ns[4], ns[5], ns[6], ns[7]) 
    nextf="" 
    nsc = ns[0:6] # first 6 elements only 
    for nsi in nsc: 
    nextf = "%s%5s" % (nextf, nsi) 
    print nextf 

...这里是一个小测试:

$ while true; do echo "1 12 123 1234 1 12 123 1234 "; sleep 1; echo "100 1 123 12 1 12 123 1234 "; sleep 1; done | ./columnizeline.py 
    1 12 123 1234 1 12 123 1234 
100 1 123 12 1 12 123 1234 
    1 12 123 1234 1 12 123 1234 
100 1 123 12 1 12 123 1234 
    1 12 123 1234 1 12 123 1234 
100 1 123 12 1 12 123 1234 
^CTraceback (most recent call last): [...] 

干杯!