Reputation: 303
grep -A5 -E 'L337' -E 'Blue' -E 'Honda' -E 'Height: 6' ./vehicles
Using this bash code, I've filtered hundreds of results to 13 like the one below:
License Plate L337ZR9
Make: Honda
Color: Red
Owner: Katie Park
Height: 6'2"
Weight: 189 lbs
I'm trying to filter first by plate, and then remove any not Blue, and not Honda, and any shorter than 6'. My syntax is wrong and I can only return this, or any individual line matching any of the search terms.
Using -v has two problems, the first being that it's impractical to filter by every negative when I have exact positives to search for, and the second being that
grep -v 'Height: 5'
just removes the height line, leaving records that are both incompatible and incomplete.
How can I filter my results with grep, while retaining all 6 lines? Can I specify a line-by-line filter?
-
Edit: The file looks like this, only I've already grep-ed for 'L337' in the plate. The issue is that I'm having trouble treating 6 individual lines of data as a single 6-line record. -A5 lets me return 5 lines beneath the License Plate, but I don't know of a way to grep for 'Blue' without cutting License Plate and Make off the top.
License Plate L337DV9
Make: Honda
Color: Blue
Owner: Joe Germuska
Height: 6'2"
Weight: 164 lbs
--
License Plate L3375A9
Make: Honda
Color: Blue
Owner: Jeremy Bowers
Height: 6'1"
Weight: 204 lbs
--
License Plate L337WR9
Make: Honda
Color: Blue
Owner: Jacqui Maher
Height: 6'2"
Weight: 130 lbs
Upvotes: 0
Views: 188
Reputation: 8711
You can get this easily using Perl
$ perl -0777 -ne ' @a=split("--"); @b=grep { /L337/ and /Honda/ and /Blue/ and /Height: 6/ } @a; print @b ' jules.txt
License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
$ cat jules.txt # your file
License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
--
--
License Plate L337GB9
Make: Toyota
Color: Blue
Owner: Matt Waite
Height: 6'1"
Weight: 190 lbs
--
--
License Plate L337OI9
Make: Jaguar
Color: Blue
Owner: Brian Boyer
Height: 6'6"
Weight: 201 lbs
--
--
$
Upvotes: 1
Reputation: 26481
With GNU awk you can do the following:
awk 'BEGIN{RS="\n--\n?";ORS="\n--\n"; FS="\n"}
($1 ~ /L337/) && ($2 ~ /Honda/) && ($3 ~ /Blue/) && ($5 ~ /[^0-9]6'/)' file
This will pick up all Blue Honda's with a license plate starting the L337 and are between 6' and 7' high.
If the fields are not always in the same order, you have to manipulate it a bit.
awk '/License Plate/ && /L337/ { f++ }
/Make/ && /Honda/ { f++ }
/Color/ && /Blue/ { f++ }
/Height/ && / 6'2/ { f++ }
{ record = record=="" ? $0 : record ORS $0 }
/^--$/ { if (f == 4) print record; f=record=""}
END { if (f==4) print record; }
Upvotes: 1
Reputation: 303
I phrased this question poorly, but the upside is that @kvantour prompted me to realise a solution.
Given 3 lots of data like this:
License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
--
--
License Plate L337GB9
Make: Toyota
Color: Blue
Owner: Matt Waite
Height: 6'1"
Weight: 190 lbs
--
--
License Plate L337OI9
Make: Jaguar
Color: Blue
Owner: Brian Boyer
Height: 6'6"
Weight: 201 lbs
--
I want to match a plate with 'L337', that is Blue, a Honda, with an owner who is at least 6'. Or I want to remove any results that do not match all of these requirements. I do not expect to see any results with Red cars, Toyotas, or short owners, so only Erika Owens' record would be returned.
My working solution is as follows:
grep -A5 'L337' ./vehicles | grep -B1 -A4 'Honda' | grep -B2 -A3 'Blue' | grep -B4 -A1 'Height: 6'
The discovery of -Bn allowed me to filter without losing the top lines. My thanks to everyone's contributions, and apologies for the confusion.
Upvotes: 0
Reputation: 133518
If I understood correctly you DO NOT want to print section which has any other color than blue(one could change color name in condition in case other than blue), then following may help.
awk '
/License Plate/ && value{
if(flag==1){
print value
}
flag=value=""
}
/Color:/ && $2=="Blue"{
flag=1
}
{
value=(value?value ORS $0:$0)
}
END{
if(flag==1){
print value
}
}' Input_file
Upvotes: 1