sed: Can my pattern contain an "is not" character? How do I say "is not X"?

RegexSed

Regex Problem Overview


How do I say "is not" a certain character in sed?

Regex Solutions


Solution 1 - Regex

[^x]

This is a character class that accepts any character except x.

Solution 2 - Regex

For those not satisfied with the selected answer as per johnny's comment.

'su[^x]' will match 'sum' and 'sun' but not 'su'.

You can tell sed to not match lines with x using the syntax below:

sed '/x/! s/su//' file

See kkeller's answer for another example.

Solution 3 - Regex

There are two possible interpretations of your question. Like others have already pointed out, [^x] matches a single character which is not x. But an empty string also isn't x, so perhaps you are looking for [^x]\|^$.

Neither of these answers extend to multi-character sequences, which is usually what people are looking for. You could painstakingly build something like

[^s]\|s\($\|[^t]\|t\($\|[^r]\)\)\)

to compose a regular expression which doesn't match str, but a much more straightforward solution in sed is to delete any line which does match str, then keep the rest;

sed '/str/d' file

Perl 5 introduced a much richer regex engine, which is hence standard in Java, PHP, Python, etc. Because Perl helpfully supports a subset of sed syntax, you could probably convert a simple sed script to Perl to get to use a useful feature from this extended regex dialect, such as negative assertions:

perl -pe 's/(?:(?!str).)+/not/' file

will replace a string which is not str with not. The (?:...) is a non-capturing group (unlike in many sed dialects, an unescaped parenthesis is a metacharacter in Perl) and (?!str) is a negative assertion; the text immediately after this position in the string mustn't be str in order for the regex to match. The + repeats this pattern until it fails to match. Notice how the assertion needs to be true at every position in the match, so we match one character at a time with . (newbies often get this wrong, and erroneously only assert at e.g. the beginning of a longer pattern, which could however match str somewhere within, leading to a "leak").

Solution 4 - Regex

From my own experience, and the below post supports this, sed doesn't support normal regex negation using "^". I don't think sed has a direct negation method...but if you check the below post, you'll see some workarounds. https://stackoverflow.com/questions/9053100/sed-regex-and-substring-negation

Solution 5 - Regex

In addition to all the provided answers , you can negate a character class in sed , using the notation [^:[C_CLASS]:] , for example , [^[:blank:]] will match anything which is not considered a space character .

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKRBView Question on Stackoverflow
Solution 1 - RegexTom ZychView Answer on Stackoverflow
Solution 2 - RegexChristopher MarkietaView Answer on Stackoverflow
Solution 3 - RegextripleeeView Answer on Stackoverflow
Solution 4 - RegexA BecklerView Answer on Stackoverflow
Solution 5 - Regexmohamad.waelView Answer on Stackoverflow