Какая команда (команды) будет вводить текстовый файл с разделителями табуляции и обрезать каждую строку до 80 символов?

8

У меня есть многострочные текстовые файлы (иногда) данных, разделенных табуляцией. Я хотел бы вывести файл, чтобы я мог просмотреть его - поэтому я хотел бы видеть только первые 80 символов каждой строки (я разработал текстовый файл, чтобы поместить важные элементы в первую очередь в каждой строке).

Я думал, что смогу использовать cat, чтобы прочитать каждую строку файла и отправить каждую строку следующей команде в конвейере:

cat tabfile | cut -c -80

Но это казалось сломанным. Я попытался поиграться, и grep, похоже, сработал - но потом я обнаружил, что нет, нет (не у каждой строки в файле было более 80 символов) - кажется, что вкладки считаются как отдельные символы по разрезу.

Я старался:

cat tabfile | tr \t \040 | cut -c -80

Даже при том, что это немного испортило бы мои данные, устраняя удобство чтения пробела. Но это не сработало. Ни один не сделал:

cat tabfile | tr \011 \040 | cut -c -80

Может я неправильно использую tr? У меня раньше были проблемы с tr, когда я хотел удалить несколько пробелов (кажется, версия tr, к которой у меня есть доступ на этой машине, имеет опцию -s для сжатия нескольких символов - возможно, мне придется больше с ней играть)

Я уверен, что если бы я бездельничал, я мог бы использовать perl, awk или sed, или что-то для этого.

Тем не менее, я хотел бы, чтобы решение, которое использует (POSIX?) Обычные команды, чтобы оно было максимально переносимым. Если бы я в конечном итоге использовал tr, я, вероятно, в конце концов попытался бы превратить вкладки в символы, возможно, сделать вычисление, сократить вычисления и затем превратить эти символы обратно во вкладки для вывода.

Это не должно быть одной строкой / вводится непосредственно в командной строке - сценарий в порядке.


Больше информации о tab-файлах:

Я использую tab для разбиения полей, потому что когда-нибудь я захочу импортировать данные в какую-то другую программу. Поэтому я склонен иметь только одну вкладку между частями контента. Но я также использую вкладки, чтобы выровнять вещи по вертикальным столбцам, чтобы улучшить читаемость при просмотре простого текстового файла. Это означает, что для некоторых фрагментов текста я закрываю конец содержимого пробелами, пока не доберусь до места, где будет работать вкладка, выравнивая следующее поле с полями выше и ниже.

DarkTurquoise # 00CED1 Море, Небо, Гребные лодки Природа
MediumSpringGreen # 00FA9A Полезно для деревьев Магия  
Лайм № 00FF00 Только для использования на весенних цыплятах и ​​фруктах
user3082
источник
Итак, вы хотите, чтобы 80 символов считали ширину вкладки? Вы можете заменить вкладки с соответствующим количеством пробелов, а затем использовать вырезать.
Муру
Annnnnd, как мне (легко) расширить один символ несколькими символами? Или, что более важно, с переменным количеством символов (в зависимости от того, сколько других символов в строке), поскольку я использую вкладку, чтобы выровнять материал по вертикали с различным количеством информации до / после каждой вкладки. Как я уже сказал, если бы я хотел изучить perl / awk / sed, я уверен, что смог бы, но я бы хотел что-то простое
user3082
Вы можете попробовать prс coreutils: pr -1 -t -l200 -W80 file. Увеличьте / уменьшите длину страницы (число после -l) в соответствии с вашими потребностями.
don_crissti
Дон, ваше предложение (почему это не ответ?) Дает мне приятное сообщение об ошибке. Но человек говорит: «pr - print files», так что изучите это.
user3082
Дон, сделайте это ответом, и давайте обсудим это там. У меня есть кое-что, похожее на ваше - в основном в том же формате, в основном с такими же флагами: -w вместо -W и т. Д.
user3082

Ответы:

9

Я думаю, что вы ищете expandи / или unexpand. Кажется, вы пытаетесь убедиться, что \tширина аб считается 8 символов, а не один. foldбудет делать то же самое, но будет переносить свои данные на следующую строку, а не обрезать их. Я думаю, что вы хотите:

expand < input | cut -c -80

expandи unexpandоба определены POSIX :

  • expandУтилита должна записывать файлы или стандартный ввод на стандартный вывод с \tсимволами аб заменен один или несколько космических символами , необходимых для прокладки к следующей позиции табуляции. Любые символы возврата должны быть скопированы в выходной файл, что приведет к уменьшению числа позиций столбца для расчетов табуляции; количество позиций столбца не должно быть уменьшено ниже нуля.

Довольно просто Итак, вот посмотрим, что это делает:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

untilПетля на вершине получает набор данных , такие как ...

1 1 2 2 3 3 ...

Это происходит printfс помощью %*sфлага заполнения аргументов, поэтому для каждого из набора printfбудет заполнено столько пробелов, сколько содержится в числе аргументов. К каждому из них добавляется \tсимвол ab.

Все из teeних используются, чтобы показать эффекты каждого фильтра, как он применяется.

И эффекты таковы:

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

Эти ряды выстроены в два набора, как ...

  1. вывод printf ...; echo
  2. вывод tr ...илиexpand
  3. вывод cut
  4. вывод wc

Верхние четыре строки - это результаты trфильтра, в котором каждый \tab конвертируется в один пробел .

И в нижней четверке результаты expandцепочки.

mikeserv
источник
1
На самом деле, не имеет значения (слишком много), если \ t считается как 8 (5?) Или единица, просто он не считается как один и отображается как 8.
user3082
+ @ anon3202 - имеет смысл. Я понимаю, что вы имеете в виду - (и, между прочим, длина остановки табуляции - это опция cli) - я просто сказал не так хорошо, как мог бы. Надеюсь, вы понимаете суть - как я понимаю, вы могли бы иметь.
mikeserv
Я не совсем следовал объяснениям, но разминка с экспандами показывает, что экспанат определенно то, что я искал.
user3082
3

Поскольку вкладки предназначены скорее для выравнивания, чем для разграничения, одним из способов может быть использование, columnа затем cut:

column -s '\t' -t <some-file | cut -c -80

Кажется, columnэто не POSIX. Это часть утилит BSD в Ubuntu, поэтому я предполагаю, что это довольно кроссплатформенная.

Мур
источник
При columnтаком способе OP даже не потребуется вручную добавлять пробелы для выравнивания.
Бени Чернявский-Паскин
1

Предложение Дона в комментариях было хорошим началом.

Вот что мне нужно, чтобы это (в основном) работало:

pr +1 -1 -t -m -l1000 -w 80 tabfile

-mБыло необходимо , чтобы сделать -wфлаг вступает в силу на один столбец. Страница справочника может использовать некоторую переписку, чтобы указать это.

При попытке обойти, я обнаружил, что pr выводятся \tсимволы, поэтому подача его результатов приводит к cutтой же проблеме.

-1 (флаг столбца) специально говорит на странице руководства:

Эта опция не должна использоваться с -m.

Однако без этой опции pr обрезает линии волей-неволей, намного короче указанной длины.

prтакже вставляет пробел перед (или после?) каждым словом в поле (т. е. каждое место, где у меня есть один пробел, имеет два после обработки). Если слов слишком много, вставленные пробелы игнорируют -wограничение (создание переноса). Но, что любопытно, в противном случае «не разделенные табуляцией» (т. Е. Расставленные пробелы) «столбцы» остаются выровненными.

user3082
источник
0

Одна утилита, которая должна быть полностью осведомлена о ширине экрана fold: к сожалению, у нее, похоже, нет возможности отбрасывать вместо переноса. Хотя это, вероятно, ужасно неэффективно, вы можете сделать что-то вроде

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
steeldriver
источник