I have a text file with lines like this (only the last two strings matter):

1 sometext Pattern
2 sometext Pattern  5Asda5}  
3 sometext Pattern asd2-asd  
4 sometext Pattern a-d
5 sometext Pattern   foobar  
6 sometext Pattern {asd  
7 Pattern Pattern something 123asd  
8 Pattern sometext asd    
9 Pattern 5h{1,2}b

I need to find each line with "Pattern" as last word. A word is defined in this case as string with letters and hyphens. There can be leading spaces or spaces following a string (like this: Pattern\t\t\t\t\t$)

My take at this is

egrep  '(\bPattern\b +[^a-zA-Z\-]{2,} *$)|(\bPattern\b *$)' file.txt 

to find all lines with Pattern followed by space(s) and a non-"word" at the end or with Pattern at the end. But the first part does not work as intended. I need another way to find the non-words.

Could you show me a way to grep line 1,2,3,6,9 but not the rest? I like to stay away from awk as we did not cover it in class.

  • Yes that is correct, my output is only line 1 – JDizzle Jun 23 '17 at 14:11
  • Please edit your original question with a sample output. – hschou Jun 23 '17 at 15:12
  • @hschou, the OP does say they want lines 1,2,3,6,9 (I also missed that initially). – Stéphane Chazelas Jun 23 '17 at 15:17

Note that \b, in grep implementations that support it, is for the transition between a word character (alnum and underscore) and non-word character (or vise versa). So \bPattern\b would match in foo-Pattern.bar for instance.

If you're looking for a blank-delimited Pattern word, you can't use \b.

Here, it seems you're looking for a blank-delimited Pattern that is followed by a list of zero or more blank-delimited strings that have characters other than letters and -, so:

grep -E "(^|[[:blank:]])Pattern([[:blank:]]+$non_word)*[[:blank:]]*$"
  • I used \bPattern\b because i know that there aren't any cases like you described, only something like aPattern or Patternn can happen. I am not used to the [:expression:] format. Would be :blank: \t and :alpha: would be [a-zA-Z0-9]? – JDizzle Jun 23 '17 at 14:30
  • @JDizzle, [:alpha:] is a character class for all alphabetical characters in the locale. Change to [:alnum:] if you also want digits. Nowadays, there's no saying what [a-zA-Z] might include unless you're in the C locale. [:blank:] is all horizontal spacing characters. In the C locale, that's space and tab. – Stéphane Chazelas Jun 23 '17 at 14:43
  • So far so good, the last thing i don't understand is why this part is necessary: non_word='([^[:blank:]]*, in the grep command we say that there may be leading blanks, so why we tell then there cant be leading blanks. And why there is no + or * after [:alpha:]? why does the Pattern non_word repeat itself? – JDizzle Jun 23 '17 at 15:04
  • @JDizzle, It's not that there can't be leading blanks. It's that non-words are sequences of 0 or more (*) non-blanks (so can be letters, digits, anything except blanks) following by one of those characters that make non-words (so there is at least one) followed by zero or more non-blanks. – Stéphane Chazelas Jun 23 '17 at 15:11
  • This pattern will accept anything that only has non-words (after the word "Pattern"), but all mixed content (words and non-words) like sometext Pattern abcd word ow{ord will be rejected. It is not clear from the OP description if that is valid or not, but interesting to know. – Arrow Jun 23 '17 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.