1

I have read that egrep is deprecated in favour of grep -E so I'm looking back at my code and changing it where I find it. But I see that the results are not always as expected.

With egrep, I get my list of running Oracle instances:

ps -ef|grep [p]mon|awk -F'ora_pmon_' '{print $NF}'|egrep -v 'ASM|^$'
halana
bila
halsasa
loana

However with grep -E, I get part of the awk in the results:

ps -ef|grep [p]mon|awk -F'ora_pmon_' '{print $NF}'|grep -Ev 'ASM|^$'
halana
bila
halsasa
 {print $NF}
loana

Excluding 'print' obviously works but is it the right way to go about it?:

ps -ef|grep [p]mon|awk -F'ora_pmon_' '{print $NF}'|grep -Ev 'ASM\|^$|print'
halana
bila
halsasa
loana

Is this effect due to the fact that grep -E allows additional regular expression syntax?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Stuart
  • 44
  • 5
  • Thanks for sharing your efforts, please do add samples of input and expected output also in your question to make it more clear, Thank you. – RavinderSingh13 Feb 15 '22 at 11:56
  • 2
    If you're actually getting part of the `awk` program in your results, that wouldn't have anything to do with `grep` (it can't reach back and somehow make `awk` produce unexpected output). That looks more like an `awk` failure, but without a reproducible example it's hard to tell. – larsks Feb 15 '22 at 11:57
  • 3
    Not sure, but may be related to `ps` including the processes of the commands being executed themselves (see https://stackoverflow.com/questions/8965509/why-if-ps-aux-grep-always-succeeds-in-bash). As a workaround, why not remove the final grep and add it to `awk`? Something like `awk -F'ora_pmon_' 'NF && !/ASM/{print $NF}'` .. and perhaps remove both grep and use `awk -F'ora_pmon_' 'NF>1 && !/ASM/{print $NF}'` (guessing based on shown samples) – Sundeep Feb 15 '22 at 13:10
  • The surprise isn't that you see the `awk` command in your `ps` output when using `grep -E`; the surprise is that you _didn't_ ever get it using `egrep`. The original code was just as buggy as the new code is, insofar as it doesn't filter its own pipeline components out of the `ps` output. (That's part of why @DudyBoy's answer is a good one). – Charles Duffy Feb 15 '22 at 13:51
  • 1
    Remember, the point of `grep [p]mon` is to make that `grep` command itself not contain the string `pmon`, but then you have `ora_pmon` right there in your awk command! You'd need to make it `ora_[p]mon` or such in the awk to not have the bug. – Charles Duffy Feb 15 '22 at 13:53
  • 1
    Also, you should quote `[p]mon` -- otherwise the shell will change it to just `pmon` when you run the code in a directory that has a `pmon` file. – Charles Duffy Feb 15 '22 at 13:58

2 Answers2

3

Suggesting to simplify your line, eliminate all grep commands:

pgrep -af 'pmon'|awk -F'ora_pmon_' '!/ASM|^$/{print $NF}'

Fold first grep command into pgrep command.

Fold second grep command into awk scirpt !/ASM|^$/{print $NF}

Dudi Boy
  • 4,551
  • 1
  • 15
  • 30
  • Hi Dudi. Thank you for that. It looks elegant. Unfortunately, I forgot to say I am using AIX. And that doesn't have a pgrep. – Stuart Feb 15 '22 at 17:49
  • The alternative to `pgrep -af 'pmon'` in AIX is `ps -ef | grep pmon | grep -v grep` . Good luck. – Dudi Boy Feb 15 '22 at 18:03
  • @DudiBoy no, the alternative to `pgrep -af 'pmon'` is `ps -ef | grep '[p]mon'`. – Ed Morton Feb 15 '22 at 23:03
2

About grep -E vs egrep

There is no difference whatsoever between these commands (they're even provided by the same executable on most operating systems); your old code was vulnerable to this bug too, and if you didn't see it, that's just a matter of being "lucky" in ps getting enough of the process list read before the shell gets to setting up the awk part of the pipeline.

Solving Your Problem

The right answer is already given by @DudiBoy, but the answer with the smallest possible change would be to make your awk (assuming it has GNU extensions and accepts regexes in the field separator specification) escape the string pmon the same way your first grep command does:

ps -ef|grep '[p]mon'|awk -F'ora_[p]mon_' '{print $NF}'|grep -Ev 'ASM|^$'
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    All awks accept a regexp as the **field** separator, you're probably confusing it's availability with a regexp as the **record** separator which only some awks such as GNU awk allow. – Ed Morton Feb 15 '22 at 23:07