Пожалуйста, помогите мне с группировкой grep regex - PullRequest
3 голосов
/ 08 ноября 2019

Я хочу очистить некоторые выводы из grep для tmux, используя.

Вот журнал:

Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:03:00.0:       VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x001F9122
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:03:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x001F9121
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002

Я хочу получить только дату и адрес pci для строки FAULT_ADDR:

Nov 07 14:51:50 03:00.0
Nov 07 14:51:50 02:00.0

Или идеальным способом:

Nov 07 14:51:50 ==> 03:00.0
Nov 07 14:51:50 ==> 02:00.0

Я сделал это:

grep -Po '([A-Za-z]{3} [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})|(?<=amdgpu 0000:).*?(?=:   VM_CONTEXT1_PROTECTION_FAULT_ADDR)' | sed ':a;N;$!ba;s/\n/ PCI /g' | sed 's/$/\n/'

но теперь все результаты идут в одной строке, а не в строке.

Я застрял с соответствием grep, потому что любое сопоставление группы выводит grep как новую строку. Также я не понял, как исключить захват даты из строки, которая не содержит FAULT_ADDR.

1 Ответ

1 голос
/ 08 ноября 2019

Вы можете использовать решение awk, например

awk '/FAULT_ADDR/{s=index($7,":"); $7=substr($7,s+1,length($7)-s-1); print $1" "$2" "$3" => "$7}' file > outfile

Подробнее

  • /FAULT_ADDR/ - найти строку, содержащую FAULT_ADDR
  • {s=index($7,":"); $7=substr($7,s+1,length($7)-s-1); print $1" "$2" "$3" => "$7} - установите s в качестве начального индекса первого :, затем установите в седьмом поле подстроку между первым : и последним, кроме одного символа, и затем объедините Поле 1, Поле2, поле 3, «=>» и поле 7 и напечатайте значение.

См. онлайн-демонстрацию :

s="Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:03:00.0:       VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x001F9122
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:03:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x001F9121
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002
Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0:       VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0A084002"

awk '/FAULT_ADDR/{s=index($7,":"); $7=substr($7,s+1,length($7)-s-1); print $1" "$2" "$3" => "$7}' <<< "$s"

Вывод:

Nov 07 14:51:50 => 03:00.0
Nov 07 14:51:50 => 02:00.0

sed решение, если вам нравится sed больше:

sed -n -E '/FAULT_ADDR/{s/^([[:alpha:]]+ +[0-9]+ +[0-9:]+).*([0-9]{2}:[0-9]{2}\.[0-9]):.*/\1 ==> \2/p}' file > outfile

См. онлайн-демонстрацию

Здесь,

  • -E - включить синтаксис регулярных выражений POSIX ERE
  • -n - подавить вывод строки
  • /FAULT_ADDR/ - найти строку, имеющую FAULT_ADDR, и только если найденпопытка замены:
  • ^ - начало строки
  • ([[:alpha:]]+ +[0-9]+ +[0-9:]+) - Группа 1: буквы 1+, пробелы 1+, цифры 1+, пробелы 1+, цифры 1+ /двоеточия
  • .* - любые 0+ символов
  • ([0-9]{2}:[0-9]{2}\.[0-9]) - группа 2: 2 цифры, :, 2 цифры, . и цифра
  • :.* - : и остальная часть строки
  • /\1 ==> \2/p} - заменить на группу 1, ==>,Сгруппируйте 2 и напечатайте результат замены.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...