There are a couple of strange things here. First, as I just learned trying to answer your question (thanks!), sed
has a cool trick:
/foo/s//bar/
This means "if this line matches foo
, then replace whatever was matched by foo
with bar
. I don't really understand the point of it, to be honest, you could do the same thing with a simple s/foo/bar/
, but there you go.
As for the regex:
^
: match the beginning of the line.
[^:]*
: when the ^
is inside square brackets, that is a negative character set. So, while [abc]
means a
or b
or c
, [^abc]
means anything except a
, b
or c
. So, [^:]*
will match 0 or more non-:
.
[eE]xception
: this matches exception
or Exception
.
:.*
: matches a :
and then everything else until the end of the line.
- Finally, the first part is in escaped parentheses (
\( \)
) which means that whatever was matched is captured and can be referred to later as \1
.
The next bit is the substitution operator, here s//\1/p
. This means substitute whatever was matched before (including the non-captured part, so the whole line) with whatever was captured (\1
). The result is that only whatever was on the line up to and including the word expression
(or Expression
) will be printed. And, since the -n
suppresses output, the p
at the end means "print this line if the substitution was successful.
Finally, the uniq -c
will give you the number of lines matching the pattern found in your file. note that it is not the number of times the word exception
occurs in the file. If you have more than one exception:
on the same line, that will be counted as one.
/foo/s//bar/
, but it's a consequence of another feature of sed - if a search pattern is empty, it reuses the last pattern. Vim also does this. In this case, I think it's a side effect of how the command was created - the author probably experimented with simple matching and then just added in a substitute command. – muru Nov 02 '17 at 18:04