Как напечатать с помощью awk красивый формат таблицы вместе со столбцом (NF )и номером строки (NR )?

Вы можете использовать trдля преобразования потока в поток, который вы можете нормально обрабатывать:

stream | tr 'x\n' '\0x' | grep -qz xxx

Это превращает все xбайты в нулевые байты, а все байты перевода строки — в xs, которые можно извлечь как обычно. То есть он перемещается на один шаг по пути перевода строки -> x -> null, поэтому последовательность из трех переводов строки теперь будет последовательностью из трех xs, и никакие другие xбайты не появятся (они станут нулевыми, завершающими строками дляgrep).


Это работает с POSIX tr, но grep -zявляется расширением. Вам может это не нужно -поведение разделения здесь не требуется -и большинство greps будут обрабатывать двоичные данные, но POSIX grepтребуется только для работы с текстовые файлы , так что вы так или иначе будете зависеть от расширения.

Если ваши настоящие данные представляют собой текстовый файл или просто не зависят от -безопасного поведения двоичных файлов, вы, вероятно, сможете выжить только

stream | tr 'x\n' '\nx' | grep -q xxx

-, то есть просто поменять местами два байта. Это почти POSIX -совместимо, но, вероятно, будет работать на практике почти везде (проблема в том, что последняя строка не будет завершена правильно, поэтому это не текстовый файл,так что grepне обязательно принимать его).

Одна из возможных проблем в любом случае заключается в том, что файл без существующих xбайтов будет рассматриваться как одна очень длинная строка, которая может превысить ограничения, которые может обработать ваша grepреализация. Выбор другого ожидаемого от -до -общего байта -может обойти это.

Я был удивлен, что ваша первоначальная команда grep -qz $'\n\n\n'не работала, но у меня была ложная-положительная проблема для меня -она вела себя как grep -qz ''и всегда совпадала. Я не уверен, почему это так.

0
29.01.2021, 21:01
3 ответа

Раздел BEGINвыполняется до открытия любого входного файла, поэтому запуск for loopне принесет вам пользы, так как первая строка ввода еще не прочитана, поэтому вы не знаете, сколько там полей. должны зациклиться. Если вы не добавите getline, но это совсем другая банка червей (, см.http://awk.freeshell.org/AllAboutGetline).

Я бы позволил awkсоздать содержимое полей, а затем позволить columnотформатировать его для интервалов, например.:

$ awk '
    NR==1 { for (i=1; i<=NF; i++) printf " %s", i; print "" }
    { print NR, $0 }
' file  | column -s' ' -t
   1  2
1  a  b
2  b  c
3  c  d

Если ваш входной файл может содержать несколько пробелов или табуляций между полями, просто измените последнюю строку awk-скрипта с { printна { $1=$1; print.

2
18.03.2021, 22:33

Вы можете использовать цикл for для перебора полей. NR — номер текущей строки, NF — количество полей в этой конкретной строке.

{   printf ("%4d", NR);
    for (f = 1; f <= NF; ++f) printf (" %-6s", $f);
    printf ("\n");
}

Для заголовка вам нужно дождаться первой строки, чтобы узнать, сколько столбцов вам нужно пометить. Итак, это идет перед предыдущим кодом. Обратите внимание, что в качестве метки выводится само f, а не $f, представляющее содержимое поля.

NR == 1 {   printf ("%4d", NR);
    for (f = 1; f <= NF; ++f) printf (" %-6s", f);
    printf ("\n");
}

Вам нужно найти максимальную ширину поля, чтобы сохранить выравнивание. Каждый % -6s означает «строковое поле, выровненное по левому краю и дополненное пробелами до 6 символов».

Отредактируйте :для более продвинутой версии, вы можете хранить все данные в массиве 2 -D, проиндексированном [NR, NF], и выводить их в блоке END. Затем вы можете сделать еще две вещи:

(1 )Для каждого столбца найдите максимальную ширину любой ячейки и зафиксируйте формат % -10 с фактической шириной для этого столбца.

(2 )Для каждого столбцаесли он имеет все числовые значения, исправьте его %s вправо -, чтобы выровнять значения.

0
18.03.2021, 22:33

Мы можем генерировать таблицы, используя оболочку groff tbl, которая генерирует код groff для создания таблиц в соответствии с требуемой архитектурой.

Здесь на основе данных мы динамически генерируем код для утилиты tbl, которая должна генерировать код для утилиты набора текста groff, используя утилиту awk:

< file \
awk '
  BEGIN {
    OFS = "@"
    print ".TS"
    print "box,tab(", ");"
  }

  !NF {next}

  NR==1 {
    fx(" ", "c", "c", ".")
    fx(OFS) 
  }

  { $1 = NR OFS $1 };1

  END { print ".TE" }

  function fp(str, sep) {
    printf "%s%s", sep, str
  }

  function fx(sep, a, b, c,   i) {
    fp(a)
    for (i=1; i<=NF; i++)
      fp(b""?b:i, sep)
    fp("\n", c)
  }
' - | tbl - | groff -Tascii | grep.

Выход:

+----------+
|    1   2 |
|1   A   B |
|2   B   C |
|3   C   D |
+----------+
1
18.03.2021, 22:33

Теги

Похожие вопросы