Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use POSIXLY_CORRECT in grep?

There is a variable POSIXLY_CORRECT in Bash

POSIXLY_CORRECT

If this variable is in the environment when Bash starts, the shell enters POSIX mode (see Bash POSIX Mode) before reading the startup files, as if the --posix invocation option had been supplied. If it is set while the shell is running, Bash enables POSIX mode, as if the command

set -o posix

had been executed.

I was told that some options of grep are not POSIX and so I confirmed in The Open Group Base Specifications Issue 6 for grep. So I checked the GNU grep manual and found:

grep comes with a rich set of options: some from POSIX and some being GNU extensions. Long option names are always a GNU extension, even for options that are from POSIX specifications. Options that are specified by POSIX, under their short names, are explicitly marked as such to facilitate POSIX-portable programming. A few option names are provided for compatibility with older or more exotic implementations.

And it also mentions:

2.2 Environment Variables

The behavior of grep is affected by the following environment variables.

POSIXLY_CORRECT
If set, grep behaves as POSIX requires; otherwise, grep behaves more like other GNU programs. POSIX requires that options that follow file names must be treated as file names; by default, such options are permuted to the front of the operand list and are treated as options. Also, POSIXLY_CORRECT disables special handling of an invalid bracket expression. See invalid-bracket-expr.

Using the part Long option names are always a GNU extension, even for options that are from POSIX specifications I said: let's try the variable POSIXLY_CORRECT against that.

So I did try with something that is not POSIX:

$ echo "HELLO" | grep --ignore-case 'hello'
HELLO

But to my surprise it also works setting it:

$ echo "HELLO" | POSIXLY_CORRECT=1 grep --ignore-case 'hello'
HELLO

What am I doing wrong? Shouldn't a set POSIXLY_CORRECT make grep not recognize a long option name?

The same occurs if using an option (for example -C) that is not POSIX:

$ POSIXLY_CORRECT=1 grep -C 2 '2' <<< "1
2
3"
1
2
3

As well as doing all the same running set -o posix before.

like image 212
fedorqui 'SO stop harming' Avatar asked Jul 27 '16 06:07

fedorqui 'SO stop harming'


1 Answers

From the GNU grep manual:

POSIXLY_CORRECT

If set, grep behaves as POSIX requires; otherwise, grep behaves more like other GNU programs. POSIX requires that options that follow file names must be treated as file names; by default, such options are permuted to the front of the operand list and are treated as options. Also, POSIX requires that unrecognized options be diagnosed as "illegal", but since they are not really against the law the default is to diagnose them as "invalid". POSIXLY_CORRECT also disables _N_GNU_nonoption_argv_flags_, described below.

This means that the only thing that setting POSIXLY_CORRECT in the environment does for GNU grep is that it's not allowed to rearrange options that occur after the filename so that the are placed at the front. It doesn't make it not take non-POSIX command line flags.

So let's try that:

$ ggrep "hello" myfile -v

$ env POSIXLY_CORRECT=1 ggrep "hello" myfile -v
ggrep: -v: No such file or directory

(GNU grep is called ggrep on my BSD system)

The part about "unrecognized options" in the manual is what GNU grep does by default, i.e. the -g flag will be diagnosed as "invalid" under both with POSIXLY_CORRECT and without. Since e.g. --ignore-case is a valid option (though not POSIX), this is not diagnosed as "invalid" with POSIXLY_CORRECT.

In general, check the documentation for external utilities for how they behave under POSIXLY_CORRECT (if they care at all). The bash manual can only tell you how the shell and its built-in commands are affected by this environment variable.

like image 118
Kusalananda Avatar answered Oct 14 '22 18:10

Kusalananda