Regex to find a dash not followed by letters

Asked

Viewed 135 times

-1

I have the following situation:

const a = "          s - al";

console.log(a.match(/^-|(?<![a-zA-Z0-9])-/))

This current regex returns a match in "-", but it should not, because there is a letter preceded that is the "s".

How do I pick up only the first stroke that nay is preceded by letters, as is this case:

     - este traco
- este tambem
          - - somente o primeiro traco deve ser pego
  • I don’t understand very well what you want... You want to match in "-" at the beginning of your string? Match in the first "-"? Match only when the string starts with "-"? In your first example there are spaces, in the following examples, no. They should be ignored?

1 answer

1

Your regex takes the hyphen that’s at the beginning (^-), or a hyphen that doesn’t have a letter immediately before. As in your code the string has a space immediately before the hyphen, regex finds a match.

In this case you should consider that there may be spaces between the letter and the hyphen, for example. But using lookbehind you get a little limited because the Engines de regex tend to be restrictive on this construction (many do not let put quantifiers, which would be an option for optional spaces, for example), in addition to not working well on all browsers - see more about this here and here.

Anyway, I would be:

console.log(a.match(/^-|(?<![a-zA-Z0-9]\s*)-/));

That is, after the letters/numbers, I have \s* (zero or more spaces). Remembering that lookbehind not supported on all browsers, and include quantifiers in a lookbehind also not allowed in many Engines.

Detail: if the string is "s - - al", she will give match in the second hyphen (it was not clear whether or not it should be found).


Unused lookbehind

If the idea is to take the first hyphen that has no letter or number in any previous position, then I find it easier to do so:

const a = "         s - al";
let pos = a.indexOf('-');
if (pos < 0 || /[a-zA-Z0-9]/.test(a.slice(0, pos))) {
    console.log('não encontrou');
} else {
    console.log(`encontrou na posição ${pos}`);
}

I mean, first I look for the hyphen. If found, I see if in any previous position has a letter or number (using a simpler regex, without lookbehind).

It may seem that it got worse just because "there are more lines", but I think to make a regex for it, although I believe it is possible, would be too complicated to be worth. Smaller code is not necessarily better.

I also return to the hyphen position because it seems more useful than returning the hyphen itself. After all, I already know I’m searching for a hyphen, so returning this character is redundant - and in case I have more than one hyphen in the string, how will I know which one gave match? So I think returning the position makes more sense in this case.

If the idea is to see if before the hyphen has a letter followed by zero or more spaces, just change the above regex to /[a-zA-Z0-9]\s*$/(it was not clear the criteria, but it seems that it can only have spaces between the letter and the hyphen).


And there’s one more thing that wasn’t clear. If the string is for example "x - - al", the first hyphen is preceded by lyrics, but what about the second hyphen? We can consider that yes (after all, it has an "x" in a previous position), or no, because we only count after the first hyphen?

If it is the first option, the above code already solves. But if it is the second option, you would have to go looking for hyphens until you find one that satisfies the condition (or until you have none at all):

const a = " x -  - al";
let pos = 0;
let posicaoEncontrada = -1;
while (pos < a.length) {
    let anterior = pos;
    // procura a partir da posição do último hífen encontrado
    pos = a.indexOf('-', pos);
    if (pos < 0)
        break;
    if (/[a-zA-Z0-9]/.test(a.slice(anterior, pos))) {
        pos++;
    } else {
        posicaoEncontrada = pos;
        break;
    }
}

// encontra o segundo hífen (posição 6)
if (posicaoEncontrada >= 0) {
    console.log(`encontrou na posição ${pos}`);
} else {
    console.log('não encontrou');
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.