1

I've got an exercise to do in which I have been given a fictional email record in which the owner of the email got invited to a certain place for vacation. The log is large though, so to speed things up, I have to use grep in a certain way to find the address where the owner of the email address is heading.

The basic form of how an address is written as:

name firstName
streetName streetNumber
postalCode(zip) City

Now I know that postal codes usually are 5 digits long, so I can start looking for the line with the postal code. Until now, I did it like this:

grep -C2 ^[0-9][0-9][0-9][0-9][0-9] emails

This command gives me all lines that start with 5 digits in a row and its surrounding two lines (-C2). With this I was really able to find the address, yet there's still a lot of unnecessary lines that show up around it. I have to specify the search to only get the address.

So I tried searching for a line that starts with 5 digits and ends with any letter like this:

grep -C2 ^´[0-9][0-9][0-9][0-9][0-9][A-Z]$´ emails

But it ends up finding nothing. It's probably because it searches for a line that only contains 5 characters and a letter. But I don't know how to tell grep to search for a line that only searches for a line that starts with 5 digits AND ends with a letter (or even better, a word).

My next best try would be searching for the name and the first name by searching for a line which contains only two words. But I don't know how to do that and I can't find any discussion in which this is explained.

I hope you guys can help me out, please?

6
  • 1
    Can you include some actual examples of real data, because I don't understand the details. Give a working example of what you have to find, what you have to find it in, and what you want to output. May 5, 2016 at 10:48
  • You should be using the word "character" where you've used "cipher".
    – symcbean
    May 5, 2016 at 11:02
  • Your final grep statement does exactly what you thought it did -- "starts with 5 digits AND ends with a letter". It will not match a line that ends in a word, because you've told grep you want one letter and then the end of the line.
    – Jeff Schaller
    May 5, 2016 at 11:03
  • @symcbean I noticed that too and tried to adjust it to what I thought they meant.
    – Jeff Schaller
    May 5, 2016 at 11:03
  • @symcbean Yeah but if I change it to character that means that it could also be a letter but i need 5 "ciphers"(numbers)
    – Ken Hado
    May 5, 2016 at 11:47

2 Answers 2

2

You can use grep -B2 -E '^[0-9]{5} +[a-zA-Z]+$' to try to find only address blocks.

Some notes:

  • see man grep to get an understanding of the options
  • see the end of the manpage for grep to find a manpage that explains the regex syntax in detail, the GNU grep manpage itself also explains regex a little
  • -B is "lines before the match" and might be better suited for you than -C
  • -E is for extended regex syntax
  • the regex I gave matches any line that has five digits ({5} takes the preceding thing five times), then at least one space (+ takes the preceding thing one or more times) and then only letters till the end of the line.
  • take care how you quote your arguments to grep. ` is very different from ' or ".

You can try to find lines containing only two words if you try to find lines that contain only one space:

grep -E '^[^ ]+ [^ ]+'

If you want to match something over multiple lines I am not sure if grep can do it. You could try to do it with sed which can load the next lines into the pattern space with N and then match against that concatenation (have a look at man sed if that might suit you). (Or perl, I think it can match multi line patterns but I don't know how.)

0

So I tried searching for a line that starts with 5 digits and ends with any letter like this:

^[0-9][0-9][0-9][0-9][0-9][A-Z]$

That pattern matches lines that contain only 5 digits and a (capital) letter. If you expect there to be more between them, you will need to include it in the pattern. If you don't care what goes between them, use .* to match any character, unlimited times. You should probably also include lower-case letters, or use grep -i to ignore case.

^[0-9]\{5\}.*[A-Za-z]$

My next best try would be searching for the name and the first name by searching for a line which contains only two words. But I don't know how to do that and I can't find any discussion in which this is explained.

You could match lines that contain two simple words, with a pattern that runs: start, word, gap, word, end:

^[[:alpha:]]\+[[:space:]]\+[[:alpha:]]\+$

However, attempting to match a name with a regular expression has many pitfalls. See https://stackoverflow.com/questions/2385701/regular-expression-for-first-and-last-name .

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .