#linux #formatting #stream #stdout
#linux #форматирование #поток #стандартный вывод
Вопрос:
Я хотел бы отформатировать текстовое содержимое, которое я получаю в виде потока стандартного вывода, используя column
, но у меня не получается. Например, при использовании одной строки все работает нормально:
$ 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
также нужен полный файл)…
Заранее спасибо,
Ура!
Комментарии:
1. Скорее всего, столбец должен прочитать все входные данные, чтобы решить, какой ширины сделать каждый столбец. Таким образом, вы не можете использовать его с «бесконечными» потоками, иначе он в конечном итоге поглотит всю память.
2. Спасибо за подтверждение @Keith — Я предполагаю, что это так, и
column
здесь неприменимо; но существуют ли альтернативные инструменты, которые работали бы «на строку» вместо «на файл»? Я предполагаю, что в этом случае количество столбцов и ширина столбца должны быть указаны априори, но для моего использования это нормально.. Приветствия!3. Вместо этого вы могли бы передать его в sed и заменить пробелы табуляциями, а терминалы tabstops отформатировать его в столбцы.
... | sed -e 's/[ ] /t/g'
4. Спасибо за это, @Keith —
sed
кажется, что с этими «бесконечными» потоками все работает нормально; Я бы предпочел «реальные столбцы», поскольку это числовые данные, поэтому я хотел бы выровнять их по правой границе «слова»; тогда как вкладки выравниваются по левому краю…. Но все равно, вкладки намного лучше, чем раньше 🙂 Приветствия!5. @Keith: ты опередил меня, только что закончил редактировать мой другой пост, чтобы предложить sed 🙂
Ответ №1:
Я тоже разочаровался в column из-за невозможности потоковой передачи, а код sdaau — из-за неспособности измерить мои столбцы. Итак, вот исправление обеих этих проблем. Возможно, это не очень эффективно, но в любом случае это просто для отладки. У меня это есть в моей папке ~ / bin как pcol
(обязательно укажите 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('').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)
Комментарии:
1. Большое спасибо за это, @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
«, и все работает отлично 🙂 Перенес accept тоже; еще раз спасибо — ура!
Ответ №2:
Ответа нет, потому что ваша вторая команда создает бесконечный цикл, а затем запрашивает, чтобы после завершения результат был передан в column -t. Поскольку цикл никогда не завершается, column -t ничего не делает. Я не уверен, чего вы пытаетесь достичь, но вариант 2nd command, который выдает вывод с интервалом в одну секунду (я предполагаю, что вы этого хотите), заключается в следующем:
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'
Комментарии:
1. Привет @user507078 — спасибо за это, но я использовал
while
конструкцию просто для имитации бесконечного потока, как при чтении потока с устройства, как вcat /dev/ttyUSB0
— где данные отображаются каждую секунду…
Ответ №3:
Хорошо, благодаря ответам здесь, мне удалось создать скрипт на 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('').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): [...]
Приветствия!