3

I want to clearify some outputs from grep for tmux using.

Here is a log:

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

I want to get only date and pci address for FAULT_ADDR string:

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

Or in perfect way:

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

I've made this:

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/'

but now all results goes in one string, not in row.

I am stuck with grep match, because any group match grep outputs as a new string. Also i didnt understand, how to exclude date capturing from string that doesnt contains FAULT_ADDR.

1
  • sorry, my fault, log past was incorrect, just updated
    – navy
    Commented Nov 8, 2019 at 13:29

1 Answer 1

1

You may use an awk solution like

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

Details

  • /FAULT_ADDR/ - find a line that contains FAULT_ADDR
  • {s=index($7,":"); $7=substr($7,s+1,length($7)-s-1); print $1" "$2" "$3" => "$7} - set s to the start index of the first :, then set the seventh field to a substring between the first : and the last but one char, and then concatenate Field 1, Field 2, Field 3, " => " and Field 7 and print the value.

See the online demo:

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"

Output:

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

A sed solution if you like sed more:

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

See the online demo

Here,

  • -E - enable POSIX ERE regex syntax
  • -n - suppress line output
  • /FAULT_ADDR/ - finds a line having FAULT_ADDR and only if found the replacement is tried:
  • ^ - start of string
  • ([[:alpha:]]+ +[0-9]+ +[0-9:]+) - Group 1: 1+ letters, 1+ spaces, 1+ digits, 1+ spaces, 1+ digits/colons
  • .* - any 0+ chars
  • ([0-9]{2}:[0-9]{2}\.[0-9]) - Group 2: 2 digits, :, 2 digits, . and a digit
  • :.* - : and the rest of the string
  • /\1 ==> \2/p} - replace with Group 1, ==>, Group 2 and print the result of replacement.
3
  • echo 'Nov 07 14:51:50 SA0888 kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x001F9121' | awk '/FAULT_ADDR/{print f} {s=index($7,":"); $7=substr($7,s+1,length($7)-s-1); f=$1" "$2" "$3" => "$7}' also nothing. what i do wrong?
    – navy
    Commented Nov 8, 2019 at 13:26
  • this solution works like a charm! thank you! Nov 08 16:31:33 => 06:00.0 Nov 08 16:31:33 => 06:00.0 Nov 08 16:31:33 => 06:00.0 Nov 08 16:31:49 => 06:00.0 Nov 08 16:31:54 => 06:00.0 Nov 08 16:32:22 => 06:00.0 Nov 08 16:32:22 => 06:00.0 Nov 08 16:32:27 => 06:00.0
    – navy
    Commented Nov 8, 2019 at 13:38
  • @navy Glad it worked for you. Please also consider upvoting if my answer proved helpful to you (see How to upvote on Stack Overflow?) as you are entitled to the upvoting privilege after reaching 15 rep points. Note you may upvote all the answers that turned out helpful. Commented Nov 9, 2019 at 8:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.