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.
    – user232326
    Jun 23, 2017 at 16:30

You must log in to answer this question.

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