1

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.

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

1 Answer 1

1

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:

non_word='([^[:blank:]]*[^[:blank:][:alpha:]-][^[:blank:]]*)'
grep -E "(^|[[:blank:]])Pattern([[:blank:]]+$non_word)*[[:blank:]]*$"
6
  • 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, 2017 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. Jun 23, 2017 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, 2017 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. Jun 23, 2017 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.
    – IsaaC
    Jun 23, 2017 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.