10

Say it's very easy if I want to find something containing lower-case letters and numbers with

produce_text | grep -E '[0-9a-z]'

Brackets are useful to match a set of characters, but what about those that are somewhat special?
If I want to, using brackets, match any character but one of these: a closing bracket ], a dash (or hyphen) "-", both slashes / and \, a caret ^, a colon :.
Will it look like this (I know this doesn't work)?

[^]-/\^:]
iBug
  • 3,508

2 Answers2

11

To match a literal ] and a literal - in a Bracket Expression you'll have to use them like this:

[^]/\^:-]

or, even better, since some tools require the backslash to be escaped:

[^]/\\^:-]

that is
The right-square-bracket ( ']' ) shall lose its special meaning and represent itself in a bracket expression if it occurs first in the list (after an initial '^', if any)
and
The hyphen-minus character shall be treated as itself if it occurs first (after an initial '^', if any) or last in the list
hence
If a bracket expression specifies both '-' and ']', the ']' shall be placed first (after the '^', if any) and the '-' last within the bracket expression.
The rules for bracket expressions are the same for ERE and BRE.

don_crissti
  • 82,805
  • 2
    I'd double the backslash to be on the safe side. It's needed with many awk implementations and perl for instance. – Stéphane Chazelas Feb 05 '17 at 01:58
  • What about "From caret to closing bracket"? Like [^-]] (This one fails)? – iBug Feb 06 '17 at 23:02
  • 2
    @iBug - sure it fails as the right bracket has to be first if you want to match it literally. I'm not sure I get the point of that "range" that you mention as ^ is after ] so [^-]] would not work even if both ^ and ] were treated literally (just like [b-a]). Anyway, if you wanted to match from e.g. ; to closing bracket you could use a range up to the char before ] (which is backslash) and include ] as first char in the bracket expression so e.g. [];-\\]. – don_crissti Feb 06 '17 at 23:41
  • @don_crissti What about [[.^.]-[.-.]]? I have a feeling that this would work. Let's assume that the ASCII code of ^ is before -. – iBug Feb 07 '17 at 13:48
  • Got a lazy solution for my question. Simply get everything special to collating characters, like [^[.].][.-.]/\^:] – iBug Feb 07 '17 at 13:55
7

Strangely perhaps, you need to have a couple of characters in specific places. You must have ] as the first character in a set, and - must be the last character in a set.

Here is an RE that meets your requirements: [^]\^/-]:

echo 'Hello[world]-[sun] ^^ 4/5 or 3\4' | grep -Eo '[^]\^/-]' | xargs
H e l l o [ w o r l d [ s u n 4 5 o r 3 4
Chris Davies
  • 116,213
  • 16
  • 160
  • 287