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

У меня есть переменная, содержащая содержимое файла с несколькими строками. Переменная анализируется множеством команд (awk, sed,...), которые действуют как фильтры и постпроцессоры переменной.

echo "$variable" | awk1 | sed1 | awk2

Проблема не в самой обработке, а в том, что я модифицирую строку в процессе, теряя исходное значение переменной. Проблема в том, что конечный awk выполняет условную проверку, которая возвращает, в зависимости от результата, исходную переменную или нет. И в этом заключается моя проблема.

Я предполагаю, что было бы неплохо создать эту переменную с исходной строкой после эха, но все мои попытки унаследовать ее в следующих подоболочках не увенчались успехом. Решение должно быть переносимым (соответствовать стандарту POSIX).

Формат переменной:

John Smith - - [21/Mar/2017:09:24:33 +0100] Physics 
Adam Miller - - [22/Feb/2019:09:24:33 +0100] Chemistry 

Я хочу сравнить даты в этом файле с заданной датой в формате YYYYMMDDHHMMSS (например, 20180101151515), и если строка содержит дату после, я хочу напечатать всю строку.

Мой код до сих пор:

date_after="19960101151515"
process=$(echo "$variable" |awk -F' - - ' '{print $2}' | sed "s/Jan/01/; s/Feb/02/;
    s/Mar/03/; s/Apr/04/; s/May/05/; s/Jun/06/; s/Jul/07/;
    s/Aug/08/; s/Sep/09/; s/Oct/10/; s/Nov/11/; s/Dec/12/" | awk -F'[/:\\[ ]' -v date="$date_after" '{b=$4$3$2$5$6$7; if (b > date) {print $0}}')

person lowcase_m    schedule 11.03.2019    source источник
comment
Добро пожаловать в Stack Overflow. Ваш вопрос звучит интересно, но мы хотели бы увидеть минимальный пример того, что вы ожидаете. Выражения sed и awk не обязательно должны быть точно такими же, как в вашем исходном коде, но должны быть чем-то простым, чтобы мы могли видеть, что вы имеете в виду под «условием», и могли понять, каковы возвращаемые значения. В общем, мне кажется, что всю проблему можно решить с помощью простого awk-решения. Кроме того, это немного пахнет XY-проблемой.   -  person kvantour    schedule 11.03.2019
comment
@kvantour я добавил пример   -  person lowcase_m    schedule 15.03.2019
comment
@lowcase_m я добавил ответ   -  person kvantour    schedule 15.03.2019


Ответы (1)


Любая комбинация sed, awk, grep, cut, ... обычно может быть заменена одним awk. Это также позволяет вам сохранять исходные данные и возвращать их в зависимости от условия. Вы можете легко увидеть, что следующий awk выполняет интересующее вас преобразование (сначала awk и sed)

awk '{ t=$0
       match(t,"\\["); t=substr(t,RSTART+1)
       match(t," ")  ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
       day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6]; 
       month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
       print year month day hhmmss, t}'

Итак, теперь вы можете подключить свой условный оператор к t и вернуть исходный $0, если это необходимо:

awk -v d="$date_after" '
     { t=$0
       match(t,"\\["); t=substr(t,RSTART+1)
       match(t," ")  ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
       day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6]; 
       month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
     }
     (t > d) { print $0 }'

на основе: конвертировать месяц из От Aaa до xx в маленьком скрипте с awk

person kvantour    schedule 15.03.2019