2

I have the input below:

csdi_d_trs_proc_uxs1        26 24
csdi_d_tdp_process_uxs1     28 32

I only need the line which contains proc. When I use:

grep proc filename 

both lines are output, so I tried using grep -w proc filename, but no output is getting displayed.

How can I get the line which has only proc but not process?

  • 3
    why not to use grep '_proc_' instead of just grep 'proc'? Option -w is for words and _ is not a word delimiter. – George Vasiliou Jun 15 '17 at 7:49
  • and how this line csdi_d_trs_11proc-_uxs1 26 24 should be treated? – RomanPerekhrest Jun 15 '17 at 7:54
  • 1
    @Roman presumably it's out of scope for the question so the result of any solution would be undefined for this value. – roaima Jun 15 '17 at 17:51
11

The -w flag for grep will make the given expression match only whole words.

A "word" is a string of "word characters" surrounded by "non-word characters" (or start/end of line).

The issue in your case is that _ (underscore) happens to be a "word character", and does therefore not serve to delimit the word proc as a word on its own.

Instead of using -w with grep, use a pattern that explicitly delimits the word by _:

grep '_proc_' filename

Alternatively, use [^a-z] instead of _ if you want to delimit the word by anything that is not a lower-case alphabetical character:

grep '[^a-z]proc[^a-z]' filename

Note that this won't recognize proc as a word at the very start/end of a line though.

  • But [^a-z]proc[^a-z] will not match proc at the start or the end of the line... – ilkkachu Jun 15 '17 at 11:05
  • @ilkkachu ... and neither will _proc_. I will update. – Kusalananda Jun 15 '17 at 11:09
  • @ilkkachu On second thought, your answer covers that already. – Kusalananda Jun 15 '17 at 11:12
  • I didn't even think of that. :D _proc_ at least makes it explicit that the underscores need to be there. – ilkkachu Jun 15 '17 at 11:13
  • ilkkachu's answer accounts for line start/end by explicitly allowing them in the regex. (The use of grep -E prevents the need for six headache-inducing backslashes.) – mwfearnley Jul 28 '18 at 19:41
4

-w, --word-regexp Select only those lines containing matches that form whole words. [...] Word-constituent characters are letters, digits, and the underscore.

The underscore is valid as part of an identifier in most programming languages (at least C, Perl, shell), which is probably why it's considered a "word-character" here.

One way to match just word would be to use the negative look-ahead and look-behind tests that Perl regexes provide. Here (?<![a-z]) means "not preceded by a lower case character, and (?![a-z]) similarly for what comes after. The beginning and end of the line aren't lower case characters, so this will match proc even at the beginning:

pcregrep '(?<![a-z])proc(?![a-z])' filename 

Or with a grep ERE, taking the beginning and end of a line explicitly into account:

grep -E '(^|[^a-z])proc([^a-z]|$)' filename

(I'm not sure which one of those is prettier.)

If you have natural-language text, [[:alpha:]] might be more correct than [a-z].

But of course, just grepping for _proc_ is easier, if you know the underscores will be there.

  • grep 'proc' filename worked for me.Thanks kusal for your reply – Nithin Kumar Jun 16 '17 at 6:07

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.