Как извлекать строки в определенном порядке

У меня есть документ:

column1: 23
column2: 42
kolumn3: 24
column1: 24
column2: 35
kolumn3: 46
column1: 25
column2: 42
column1: 35
column2: 45
kolumn3: 52

И я бы хотел, чтобы мой результат был:

column1: 23
column2: 42
kolumn3: 24
column1: 24
column2: 35
kolumn3: 46
column1: 35
column2: 45
kolumn3: 52

Вывод должен быть в порядке column1, column2, kolumn3. Удалите все, что находится не в этом порядке.

Возможно ли это сделать в grep, sed или awk?

2
0
77
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это поможет в awk, назовем его testcol.awk:

$1=="column1:" {l1=$0; n=2;}
$1=="column2:" && n==2 {l2=$0; n=3;}
$1=="kolumn3:" && n==3 {print l1 "\n" l2 "\n" $0; n=1}

Затем запустите что-то вроде

awk -f testcol.awk your_input_file

Хорошая государственная машина. Моя единственная рекомендация - не использовать здесь перенаправление оболочки. Это не нужно. Просто используйте входной файл в качестве последнего аргумента командной строки.

Rafael 26.10.2018 05:18

@ Рафаэль, что ты имеешь в виду, пожалуйста? Я новичок в awk.

NoobTW 26.10.2018 05:28

Я просто указывал, что перенаправление оболочки не требуется. awk -f test.awk file достаточно.

Rafael 26.10.2018 05:31

n необходимо сбросить, иначе у вас может быть несколько "kolumn3" подряд, и он будет печатать каждую, не так ли?

flu 26.10.2018 18:55
Ответ принят как подходящий

Использование GNU awk:

awk -v RS='column1: [0-9]+\ncolumn2: [0-9]+\nkolumn3: [0-9]+\n' '{printf RT}' file

Разделитель записи RS - это регулярное выражение, предназначенное для перехвата трех последовательных строк.

Единственное утверждение - вывести терминатор записи RT, исключив все, что не было перехвачено RS.

Довольно n33t. Подойдет, если есть что-то вроде ANYTHINGcolumn1:, но, полагаю, поправимо.

James Brown 26.10.2018 10:08

@JamesBrown Нет, не будет. Он печатает только разделитель записей, ничего больше. Если перед разделителем записей есть данные мусора (как вы упомянули), он не будет печатать их. Если есть данные мусора с нужными строками, они просто не будут совпадать и не будут распечатываться.

oliv 26.10.2018 10:29

Я имел в виду, что если file будет: ANYTHINGcolumn1: 23\ncolumn2: 42\nkolumn3: 24, он будет вытеснен без учета ANYTHING.

James Brown 26.10.2018 10:46

@JamesBrown Хорошо ... Это именно то, что я понял из вопроса OP ...

oliv 26.10.2018 10:51

Другой (ошибка мозга, которая не оставляла меня в покое до того, как я его ввел, хотя довольно непроверенный):

$ awk '
BEGIN {
    p="column1:column2:kolumn3:"  # comparison pat- NO, something else ;D
}
p~"^" b $1 {                      # if gathered $1 buffer matches the p
    b=b $1                        # keep collecting
    c=c $0 ORS
    if(p==b) {                    # prefect match deserves to be outputed
        printf c
        b=c=""                    # reset buffer vars
    }
    next                          
}
{                                 # a non-match means a reset and restart 
    b=$1                          # for buffer vars
    c=$0 ORS
}' file

Выход:

column1: 23
column2: 42
kolumn3: 24
column1: 24
column2: 35
kolumn3: 46
column1: 35
column2: 45
kolumn3: 52

Это может сработать для вас (GNU sed):

sed ':a;N;/^column1:.*\ncolumn2:/!D;N;/\nkolumn3:/b;s/.*\n//;ta' file

Прочтите две строки в пространстве шаблонов и, если они не соответствуют column1:, а затем column2:, удалите первую и повторите. В противном случае добавьте третью строку, и если она соответствует kolumn3:, выведите все три строки, если нет, удалите первые две строки и вернитесь к началу сценария sed.

Другое решение:

sed -n '/\n/!N;N;/^column1:[^\n]*\ncolumn2:[^\n]*\nkolumn3:[^\n]*$/p;//!D' file

Другие вопросы по теме