Вот нечисловое путь в Awk. Это работает, если у нас есть Awk, который поддерживает переменную RS
длиной более одного символа. Мы разбиваем данные на записи на основе разделения пустой строки: "\n\n"
. Внутри этих записей мы прерываем поля на линиях новой строки. Таким образом $1
слово, $2
является определением, $3
является котировкой и $4
является источником:
awk 'BEGIN {OFS=FS="\n";ORS=RS="\n\n"} $1=$1" >>"'
Мы используем одни и те же выходные разделители в качестве входных сепараторов. Наш единственный шаблон/шаг действия - это отредактировать $1
так, чтобы на нем было >>
. Действие по умолчанию - { print }
, что и мы хотим: напечатайте каждую запись. Поэтому мы можем опустить это.
Сокращенное: Инициализация RS
от FS
.
awk 'BEGIN {OFS=FS="\n";ORS=RS=FS FS} $1=$1" >>"'
Это красиво выразительно: в нем используются два последовательных разделителя полей для разделения записей.
Что делать, если мы используем флаг, первоначально сброшенный, который сбрасывается на каждой пустой строке? Это решение по-прежнему не зависит от жестко закодированного номера, а просто для разделения пустой строки. Правило, пожары на первой линии, потому что C
оценивает до нуля, а затем после каждой пустой строки, потому что мы сбрасываем C
нулю:
awk 'C++?1:$0=$0" >>";!NF{C=0}'
Сокращенный вариант принятого решения Awk:
awk '(NR-1)%5?1:$0=$0" >>"'
Мы можем использовать тернарное условное выражение cond ? then : else
как шаблон, оставив действие пустым, чтобы оно по умолчанию было {print}
, что, конечно же, означает {print $0}
. Если нулевой номер записи равен , а не, сравнимый с 0, по модулю 5, то мы создаем 1
, чтобы вызвать действие печати. В противном случае мы оцениваем `$ 0 = $ 0" >> ", чтобы добавить требуемый суффикс в запись. Результатом этого выражения является также логическое значение true, которое запускает действие печати.
сбрить еще один символ: мы не должны вычесть 1 из NR
, а затем тест для сравнения нулю. В основном, когда 1 на основе номера записи конгруэнтно 1, по модулю 5, то мы хотим, чтобы добавить >>
суффикс:
awk 'NR%5==1?$0=$0" >>":1'
Хотя мы должны добавить ==1
(+3 символов), мы победим, потому что мы можем упасть две круглые скобки и -1
(-4 символа).
Мы можем сделать лучше (с некоторыми допущениями): Вместо редактирования $0
, что мы можем сделать, это создать второе поле, содержащее >>
путем присвоения параметру $2
. Неявное print
действие напечатает это, офсет пробелом:
awk 'NR%5==1?$2=">>":1'
Но это работает только, когда линия определение содержит одно слово. Если какое-либо из слов в этом словаре является составными существительными (разделенное пробелом, а не переносом), это терпит неудачу. Если попытаться восстановить этот недостаток, мы, к сожалению, вернулись к той же длине:
awk 'NR%5==1?$++NF=">>":1'
Незначительное изменение на подходе: Вместо того, чтобы пытаться лавировать >>
на запись или последнего поля, почему не мы условно устанавливаем >>\n
как ORS
, разделитель выходной записи?
awk 'ORS=(NR%5==1?" >>\n":"\n")'
Не the tersest, но стоит упомянуть. Он показывает, как мы можем динамически играть с некоторыми из этих переменных от записи к записи.
Различные способы тестирования NR == 1 (mod 5): а именно, regexp!
awk 'NR~/[16]$/?$0=$0" >>":1'
Опять же, не tersest, но, кажется, стоит упомянуть. Мы можем рассматривать NR
как строку, представляющую целое число в виде десятичных цифр.Если он заканчивается 1
или 6
, то он сравним с 1, mod 5. Очевидно, что не легко модифицировать другие модули, не говоря уже об отвратительном вычислении.
Вы уверены, что хотите линии 1,5,9, ...? Ваш пример, похоже, нуждается в 1,6,11,16 ... – redneb