For a block of text:
USB2.1 Hub:
Product ID: 0x0610
Dell Universal Dock D6000:
Product ID: 0x6006
Vendor ID: 0x17e9 (DisplayLink (UK) Ltd.)
Version: 31.27
Serial Number: 1810132665
Speed: Up to 5 Gb/s
Manufacturer: DisplayLink
..on detecting the string DisplayLink
(I've been using Manufacturer
but in theory either should work) I'd like to return Dell Universal Dock D6000
(or specifically, the entire line between the two lines containing Product ID
).
This should be doable with some awk
array:
awk '/DisplayLink/ { for(i=NR-8;i<NR;i++) if(i>0) print a[i]; print; exit} {a[NR}=$0}'
returned a syntax error.
Using this (admittedly ugly, inefficient) chain of tools returns the desired result:
grep "Manufacturer: DisplayLink" -B7 -n | head -1 | awk -F'[ :]+' '{ $1=""; print $0 }'
Assumptions:
Manufacturer: DisplayLink
Tweaking OP's current code (store all lines in memory, then print line # NR-7
):
awk '
/Manufacturer: DisplayLink/ { i=NR-7; if (i>0) print a[i]; exit}
{ a[NR]=$0 }
' dell.dat
An alternative to OP's code that stores just the last 7 lines (via a modulo 7 index):
awk '
/Manufacturer: DisplayLink/ { i=NR-7; if (i>0) print a[i%7]; exit }
{ a[NR%7] = $0 }
' dell.dat
Yet another alternative approach requiring two reads of the input file; first read notes the line where we find the match and then subtracts 7 (call this line_no
); the second read then prints the line where FNR == line_no
:
awk 'FNR==NR && /Manufacturer: DisplayLink/ { line_no = FNR-7; nextfile }
FNR==line_no
' dell.dat dell.dat
All of these generate:
Dell Universal Dock D6000: