3

How do I write a Javascript regular expression that matches everything except a given string ("ABCD")?

Something like /[^ABCD]/ except I don't want to match everything that isn't the letter A, B, C or D. I want to match everything that isn't the string "ABCD".

Basically I want this to happen:

var myStr = "ABCA ABCB ABCD BCD ABC"
myStr.replace(/!(ABCD)/g,'') // returns ABCD
kapa
  • 72,859
  • 20
  • 152
  • 173
brentonstrine
  • 17,958
  • 23
  • 61
  • 112

4 Answers4

5

You can simply check for ABCD, check how many of it exists in the string, then construct a new string from it like this (you can use space as a separator if it fits your case better):

var res = myStr.match(/ABCD/g);
var str = res ? res.join('') : '';

The ternary is there because match() will return null if it finds nothing - which does not have a join() method.

kapa
  • 72,859
  • 20
  • 152
  • 173
  • Good answer, but I was really looking for a way to do this with regex. – brentonstrine Aug 09 '12 at 23:11
  • 1
    @brentonstrine Well, I used regex :) – kapa Aug 09 '12 at 23:13
  • I feel like you didn't answer the spirit of my question about regex, but I did end up using `.match()` in my actual code, so thanks. +1. – brentonstrine Aug 10 '12 at 04:39
  • @brentonstrine IMO a classic regex is not the best tool to solve this problem, that's why I tried to provide an alternative. There are a thousand other ways of course, even not using a regex at all. Please accept an answer if you think it is good enough, so everyone can see the problem is solved. Of course it's no problem at all if you accept Alan's answer, it is a good one. – kapa Aug 10 '12 at 07:55
  • Whoops, I thought I had accepted his. I wish I could accept both Alans and yours. – brentonstrine Aug 10 '12 at 15:37
3

Okay, I had misinterpreted the question. It seems you want to test for the presence of ABCD, and if you find it, replace the whole string with just that: ABCD. This will do that:

s = s.replace(/.*(ABCD).*/, '$1');

But it will leave the string unchanged if there's no ABCD in it. If you want to delete the string in that case, you have to make the capture optional. But then you have to alter the first part of the regex to make it "sneak up" on the capture:

s = s.replace(/^(?:(?!ABCD).)*((?:ABCD)?).*$/, '$1');

That forces it to try to capture ABCD at every position. (It also slows things down massively--not an issue in this case, but something to keep in mind if you use this technique on large inputs.)

So a pure-regex solution does exist, but I like @bažmegakapa's solution better. :D


original answer:

/^(?!ABCD$).*/

Note that this will also match an empty string. If you have any positive requirements, you can change the .* to whatever you need. For example, to match one or more uppercase ASCII letters but not the exact string ABCD, you can use:

/^(?!ABCD$)[A-Z]+$/
Alan Moore
  • 68,531
  • 11
  • 88
  • 149
  • I may be doing something wrong, but that seems to also match `ABCD`. http://www.myregextester.com/?r=c725cba3 – brentonstrine Aug 09 '12 at 23:08
  • True, @ bažmegakapa's solution is better, and ultimately in my code, using `.match()` ended up being even simpler than his answer for my purposes, but I could have come up with a hundred other ways to address my initial issue. This question was about regular expressions! I wish I could split the "answer" but I did upvote both. – brentonstrine Aug 10 '12 at 04:38
0

This is a direct expansion of the negation , without using a negation operator:

/^\([^a]\|a[^b]\|ab[^c]\|abc[^d]\)*$\|^a$\|^ab$\|^abc$/

When you call a negation operator into some language, it transform the expression you want to negate into something like the upper form .


Here is how I tested it:

@ThinkPad-T420:~$ E='/^\([^a]\|a[^b]\|ab[^c]\|abc[^d]\)*$\|^a$\|^ab$\|^abc$/ p;d'
@ThinkPad-T420:~$ echo abc | sed "$E"
abc
@ThinkPad-T420:~$ echo abcd | sed "$E"
@ThinkPad-T420:~$ echo abcde | sed "$E"
@ThinkPad-T420:~$ echo axbcde | sed "$E"
axbcde
@ThinkPad-T420:~$ echo xxabcde | sed "$E"
@ThinkPad-T420:~$ 
alinsoar
  • 13,197
  • 4
  • 45
  • 63
0

try with this:

var myStr = "ABCA ABCB ABCD BCD ABC";
var foo = myStr.replace(/\b(?!ABCD\b)\w+\b/g,'').trim(); // returns ABCD
document.write(foo);

output: ABCD

or:

var myStr = "ABCA ABCB ABCD BCD ABCD ABC";
var foo = myStr.replace(/\b(?!ABCD\b)\w+\b/g,'').replace(/\s/g, '');
document.write(foo);

output: ABCDABCD

godspeedlee
  • 682
  • 3
  • 7