Как переместить пару строк в конец предыдущей пары строк - PullRequest
1 голос
/ 02 марта 2020

У меня большой файл с повторяющимся шаблоном из 5 строк, начинающимся с отметки даты. Я пытаюсь переместить (относительные) строки 4 и 5 в конец строк 2 и 3 соответственно:

текущий вывод:

Mon Mar  2 16:47:14 UTC 2020
    1        90    93090     1024        0        0        0    93090|
    9        73    74877     1024        0        0        0    74877|
  Dirty Cache:          860160 KB
  Dirty Cache:          0 KB
Mon Mar  2 16:47:15 UTC 2020
    1        68    69680     1024        0        0        0    69680|
    9        83    85838     1024        0        0        0    85838|
  Dirty Cache:          860160 KB
  Dirty Cache:          0 KB
Mon Mar  2 16:47:16 UTC 2020
    1        66    67794     1024        0        0        0    67794|
    9        67    68806     1024        0        0        0    68806|
  Dirty Cache:          860160 KB
  Dirty Cache:          0 KB
Mon Mar  2 16:47:17 UTC 2020
    1        42    43424     1024        0        0        0    43424|
    9        47    48473     1024        0        0        0    48473|
  Dirty Cache:          860160 KB
  Dirty Cache:          0 KB

Желаемый вывод со значениями грязного кэша на конечные строки, начинающиеся с '1' и '9':

Mon Mar  2 16:47:14 UTC 2020
    1        90    93090     1024        0        0        0    93090|  Dirty Cache:          860160 KB
    9        73    74877     1024        0        0        0    74877|  Dirty Cache:          0 KB
Mon Mar  2 16:47:15 UTC 2020
    1        68    69680     1024        0        0        0    69680|  Dirty Cache:          860160 KB
    9        83    85838     1024        0        0        0    85838|  Dirty Cache:          0 KB
Mon Mar  2 16:47:16 UTC 2020
    1        66    67794     1024        0        0        0    67794|  Dirty Cache:          860160 KB
    9        67    68806     1024        0        0        0    68806|  Dirty Cache:          0 KB
Mon Mar  2 16:47:17 UTC 2020
    1        42    43424     1024        0        0        0    43424|  Dirty Cache:          860160 KB
    9        47    48473     1024        0        0        0    48473|  Dirty Cache:          0 KB

Этот вывод генерируется после печати date и последующего зацикливания проприетарной команды для получения числовых значений c:

while sleep 1; do date && proprietary 'numerical values command' && proprietary 'dirty cache command 1' && proprietary 'dirty cache command 9'; done >2020-03-02_stats.txt

... затем с помощью некоторого basi c grep опустить заголовки столбцов и вывести числовые значения от 2 до 8.

К сожалению, я не могу отделить вывод числовых значений с помощью используемой команды, т. Е. Вывести выходные данные '1', а затем очистить значения кэша для '1', что сделало бы эту задачу простой для sed.

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

Ответы [ 5 ]

2 голосов
/ 02 марта 2020
awk '{a[NR%5]=$0} NR%5==0{printf "%s\n%s%s\n%s%s\n",a[1],a[2],a[4],a[3],a[0]}'

Сохранить 5 строк в массиве a. Затем, если текущая строка делится на 5, выведите строку со смещенным порядком.

2 голосов
/ 02 марта 2020

С awk:

awk '
  NR%5==1                    # print this line
  NR%5==2{ first=$0 }        # save this line in variable first
  NR%5==3{ second=$0 }       # save this line in variable second
  NR%5==4{ print first $0 }  # print first and this line
  NR%5==0{ print second $0 } # print second and this line
' file
1 голос
/ 02 марта 2020

Для выполнения sh вашей задачи вы действительно можете использовать sed. Следующая команда эффективна:

sed -E 'N;N;N;N;s/\n([^\n]*)\n([^\n]*)\n([^\n]*)$/\2\n\1\3/' your_file

Она работает по существу, как объяснил Камилчук в своем комментарии, который я не читал, когда публиковал свой ответ, за исключением того, что

  • the * Опция 1008 * помогает удерживать регулярное выражение немного короче (ищите его в man sed, чтобы увидеть, что он делает),
  • вам не нужно совпадать со строкой 2, так как достаточно \n s точно определить, где начинается / заканчивается каждая строка.
0 голосов
/ 03 марта 2020

Другое возможное короткое решение в GNU awk, которое обрабатывает файл в соответствии с вашим описанием:

  • Используется строка Mon в качестве разделителя записей RS, так что каждая запись представляет собой набор из 5 строк
  • Он использует новую строку \n в качестве разделителя полей (как на входе, FS, так и на выходе, OFS)
  • Затем выводится 5 поля в нужном порядке, с добавлением RS и соответствующим образом добавляя OFS с помощью оператора запятой ,.
awk 'BEGIN { RS = "Mon"; FS = OFS = "\n" } NR > 1 { print RS $1, $2 $4, $3 $5 }' your_file
0 голосов
/ 02 марта 2020

Вот решение awk для вас:

awk '/^[^ ]/ { 
  for ( x = 1 ; x <= linecount ; x++ ) 
    { print lines[x] "" dc[x] }
  linecount = 1 
  dclinecount = 1 
  print
  next
}
/Dirty Cache:/ {
  dc[ dclinecount++ ] = $0
  next
}
{ 
  lines[ linecount++ ] = $0
}
END { 
  for ( x = 1 ; x <= linecount ; x++ )
    { print lines[x] ""  dc[x] }
} 
'

Программа awk имеет несколько предположений. Вот первый из них:

  1. В строке 1 мы предполагаем, что только дата начинается в начале строки.
  2. В строке 2 мы предполагаем, что число Dirty Cache количество строк больше или равно количеству предыдущих строк. Если имеется больше строк Dirty Cache, программа не будет работать (данные не будут выводиться для дополнительных строк Dirty Cache).

Хотя этот сценарий не очень общий, он может поддерживать произвольный количество строк данных и строк Dirty Cache с указанным выше предупреждением (# 2).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...