Trying to understand why does the grep manual state the character classes with one square bracket.
Because character classes as such only have one set of brackets. You just need to put them inside bracket expressions too, which means in the end you have two sets.
The manual starts by giving the context of a bracket expression, one that has, well, the brackets around it:
A bracket expression is a list of characters enclosed by [
and ]
.
The following paragraphs assume that context.
Within a bracket expression, a range expression consists of two characters separated by a hyphen.
Finally, certain named classes of characters are predefined within bracket expressions, as follows.
The two characters and a hyphen also need to be within brackets, i.e. the whole thing is [a-f]
, not just a-f
. (*)
Character classes also go within the bracket expression, so e.g. a character class [:upper:]
is wrapped in brackets to give the bracket expression [[:upper:]]
. Or, in case you put more than just one character class within the brackets, you could have [-[:upper:][:digit:]]
which would match the dash, uppercase letters or digits. (one plain character and two character classes within a single bracket expression.)
As for why the syntax is like that, I don't know.
Note that the manual even has the full example on how to use character classes:
... for example, [[:alnum:]]
means the character class of numbers and letters in the current locale.
And it says:
Note that the brackets in these class names are part of the symbolic names, and must be included in addition to the brackets delimiting the bracket expression.
The error message you get is also described:
If you mistakenly omit the outer brackets, and search for say, [:upper:]
, GNU grep prints a diagnostic and exits with status 2, on the assumption that you did not intend to search for the regular expression [:epru]
.
So, it really doesn't look like it tells to use just one set of brackets for the whole deal.
Except that... The example for [:alnum:]
goes (and [:alpha:]
is similar):
[:alnum:]
Alphanumeric characters: [:alpha:]
and [:digit:]
; in the ‘C’ locale and ASCII character encoding, this is the same as [0-9A-Za-z]
.
This is false. [0-9A-Za-z]
is the same as [[:alnum:]]
, not [:alnum:]
. [:alnum:]
would be 0-9A-Za-z
, but either would need the outer brackets to do anything useful.
Of course, the error message also doesn't appear to mention the distinction between a character class and the enclosing bracket expression, so yes, they're being a bit unclear there.
Note that as the brackets are also glob characters in the shell, you should quote the pattern, e.g.
grep '[[:lower:]]' test
Otherwise, the pattern would be expanded by the shell to :
, e
, l
, o
, r
, or w
, if any files with those exact names exist.
(* Note that caveats apply with characters ranges, their interpretation depends on the locale, and in Bash the globasciiranges
option, which I think has been shown to act weirdly.)