ksm18
ksm18

Reputation: 93

Given line separated blocks of text, how can I return each block which contains a specific keyword?

me$ cat file.txt

Filename: 1
Organization: Bus 1 => Port 1 => Subport 1 => Device 3
Classes: Interface Video
Drivers: usbhid

Filename: 2
Organization: Bus 1 => Port 1 => Subport 3 => Device 4
Classes: Audio 
Drivers: usb-audio uvc Video

Filename: 3
Organization: Bus 1 => Port 1 => Subport 4 => Device 5
Classes: Wireless Video
Drivers: uvc  

How can I manipulate this to return the blocks which contain any given keyword?

For example: bash this --class "Video" would return:

Filename: 1
Organization: Bus 1 => Port 1 => Subport 1 => Device 3
Classes: Interface Video
Drivers: usbhid

Filename: 3
Organization: Bus 1 => Port 1 => Subport 4 => Device 5
Classes: Wireless Video
Drivers: uvc  

Writing the script to sort the --class and --driver case would be trivial, just asking particularly about the text manipulation. I'm thinking along the lines of grep Class:*$input, taking the line number, and printing everything from a a newline prior to that through the next newline, but that would have more complications and probably isn't the most efficient way to do it.

Upvotes: 1

Views: 96

Answers (1)

John1024
John1024

Reputation: 113924

To get Classes...Video:

$ awk -v RS= '/Classes:[^\n]*Video/' file.txt
Filename: 1
Organization: Bus 1 => Port 1 => Subport 1 => Device 3
Classes: Interface Video
Drivers: usbhid
Filename: 3
Organization: Bus 1 => Port 1 => Subport 4 => Device 5
Classes: Wireless Video
Drivers: uvc  

(I tested this with mawk and GNU awk and it should work with any POSIX awk [hat tip: ninjalj) but it may not be compatible with very old versions of awk.)

How it works

  • -v RS=

    This sets the record separator to be an empty string which is generally interpreted as meaning paragraphs.

  • /Classes:[^\n]*Video/

    This returns true if the record (paragraph) contains Classes:, followed by any number of any characters except newline, followed by Video. In other words, it returns true if a line contains the string Classes: and later contains the string Video. If this condition returns true, then awk performs the default action which is to print the record (paragraph).

Upvotes: 1

Related Questions