makersacademy / problem-solving

For problem-solving during the PreCourse
6 stars 2 forks source link

Stuck on step 6, #136

Closed AntonioDaria closed 6 years ago

AntonioDaria commented 6 years ago

I am not sure on how to search for multiple keywords in one file. How can you combine grep with flags and the pipe operator ('|') to filter the vehicle records for:

ShinyVerse commented 6 years ago

Sounds like you need to use regular expressions, have you had a go with them?

Check this out:

https://unix.stackexchange.com/questions/37313/how-do-i-grep-for-multiple-patterns-with-pattern-having-a-pipe-character

Hopefully it has something that can help.

olliebaum commented 6 years ago

Okay, you're asking lots of questions all at once here. Let's break this down a bit:

  1. You need a way to chain multiple grep statements together using the pipe operator ('|').

    • So grep can be used in a couple of ways. To use an example from step 2 of the mystery, when we were looking for someone named 'Annabel' in the 'people' file, we could have used grep Annabel people to get our results. In this instance we specify the file (people) for grep to filter, but if we pipe to grep, we don't need to specify a file since grep will use the result of the previous command to operate on. To use the step 2 example again, say we want to filter the results to only show matches who are women, we could use grep Annabel people | grep "F\s". Ignore the "F\s" for now - it's a regular expression that will match a capital F followed by a space, so will match people with F in the gender field. But notice how the second grep statement doesn't need a file specified because the pipe has passed the output from grep Annabel people to it. You can use the pipe '|' character like this multiple times in one line to achieve the desired result for step 6.
  2. You'll also need a way to find license plate numbers beginning with L337 and ending in 9 in a single grep statement.

    • Regular expressions will be useful for correctly filtering for a license plate beginning with L337 and ending with 9. I used . to achieve mine. It matches any number of characters, essentially meaning it will work a little like a wildcard. Say you have a list of words in a file called wordList and you want to match ones beginning with 'br' and ending with 'fast'. You could use `grep "br.fast" wordList`. It would hopefully match the word "breakfast" if it were in the file wordList. You can apply this to your number plate grep. (Note: It just so happens that for this particular set of data, you only need to find license plates beginning with L337 because all the results that gives end in '9' anyway. But let's assume that's not the case for now.)
  3. Then there's another problem: When you use grep with no flags it returns only the matching lines.

    • So in our case this means it will only return the license plate numbers. This is problematic because when we pipe to grep again to filter for colour or height, it won't find anything because we only have the license plate numbers. So we need a way to bring the related lines from any relevant license plates with us. If you check out the Detective handbook for step 6 located at clmystery/detective_handbook/step6.md, the grep flags mentioned there will be useful for making sure you return the full list of values for each vehicle record.

Hope this helps, let me know if you still get stuck after reading this and the handbook for step 6.

AntonioDaria commented 6 years ago

Hi All thanks for your suggestions, i have got close but not close enough to solve the issue. I have investigated different ways of doing it but did not get the desired outcome:

1) egrep -iA4 'L337|Honda|Blue' vehicles

2) grep -iA4 "L337.*9" vehicles |grep "Honda"|

3) grep -iA4 "L337.*9" vehicles (this is the closest but I would now need only to keep Blue Honda) Please let me know if you could help. Thanks

NadiaAiraf commented 6 years ago

Hi Antonio, looks to me like the second one was actually closest if you take the | off the end and then add in some Before (-B) and After (-A) flags.

So if you have:

grep -i -A5 "l337.*9" vehicles

This will give you all of the lines with the right license plate plus the 5 lines after that (in order: Make, Color, Owner, Height, Weight)

Then if you pipe the above with another grep searching for Honda, you also need to add the -A and -B flags with 4 lines After and 1 line Before (since Make is the second line on the list):

grep -i -A5 "L337.*9" vehicles | grep -i -A4 -B1 "Honda"

This will find all of the correct license plates and then from those license plates find all of the makes that are Honda.

Then you can continue on from there using more pipes to searching for the right color and then height.

Hope that's helped slightly

Note: I'm putting all of the flags separately at the moment just because it's less confusing for me.

ShinyVerse commented 6 years ago

With the approach of egrep '(L337|Honda|Blue)' vehicles It is going through the file line by line, if any of the conditions matches ("L337") ("Honda") or ("Blue") then it is returned in the result and you get this: (try it)

Lauras-MBP:mystery laura$ egrep '(L337|Honda|Blue)' vehicles
Color: Blue
Color: Blue
Color: Blue
Color: Blue
Color: Blue
Color: Blue
Make: Honda
Color: Blue
Make: Honda
Make: Honda
...

You want a a result after each condition. Try breaking this down and then combining it later on when you have all the parts.

So for example on the first search you want to find "L337" in vehicles: grep "L337" vehicles Which will return :

License Plate L337ZR9
License Plate L337P89
License Plate L337GX9
License Plate L337QE9
License Plate L337GB9
License Plate L337OI9
License Plate L337X19
License Plate L337539
License Plate L3373U9
License Plate L337369
License Plate L337DV9
License Plate L3375A9
License Plate L337WR9

You know that you want your search to return a certain amount of lines after the license plate (Try the previous command with that switch(flag) of how many lines you want after license plate and see what you get.)

Then with that result try to add on a new grep after initial grep.

AntonioDaria commented 6 years ago

Morning all I can now finally close the issue thank you all for your suggestion, it took me some investigation but i finally understand how the grep command works combined with flags and the pipe operator. see my solution below: grep -A5 "L337.*9" vehicles | grep -iA3 -B1 "honda"|grep -iA2 -B2 "blue"|grep -iA0 -B4 "6'"

ShinyVerse commented 6 years ago

@AntonioDaria Awesome! Good job 👍

AntonioDaria commented 6 years ago

Hi Guys I have checked my pull request after step6 and it has a red cross, i believe there should be a green tick instead. can anybody help me understanding what is required? thanks