1

I have a whole array of regexp queries to make recursively going through the string in order.

Is there a way I can do it all with 1 call such as (doesn't work)?

str.replace(/query1|query2|query3|query4|...|[0-9]+|[^]/,
             "reslt1|reslt2|reslt3|reslt4|...|procNumb|procChar");

It need only work in Firefox. Right now I'm stuck with:

str.replace(... ,function(a,b,c){if (a=="query1") return "reslt1"; ..............});

Thanks!

Edit: Sorry if confusing. Goal:

Before: "query1query3x123query2" After: "reslt1reslt3procChar(x)procNumb(123)reslt2"

The main thing is I need I to process the string 1 fragment at a time recursively, so I think I must use a super-query like that to match any, or not use regexes at all. I just wonder if there's a way to automatically pair the results to the queries when using lots of pipes. I am not so familiar with javascript regex but I couldn't find anything on mdc unfortunately.

5
  • It's not clear what you're trying to do. Can you include "before" and "after" examples (simplified ones, ideally)? Commented Feb 13, 2010 at 9:18
  • Are you trying to combine multiple str.replace calls into a single one? I don't think that is possible. Just wanted to point out that you haven't escaped ^ in your last regex, ^ means negation inside a character class. It should be [\^]. Commented Feb 13, 2010 at 9:29
  • [^] matches a single char of anything. Commented Feb 13, 2010 at 9:34
  • By ‘process recursively’, what you really mean is you're trying to write a parser, right? Commented Feb 13, 2010 at 9:57
  • From your comments, I started to get the idea this is just a lookup; I've updated my answer accordingly. Commented Feb 13, 2010 at 10:01

3 Answers 3

1

If you're trying to match any of several alternative substrings and provide a different result for each match, you're going to have to use a function (as you appear to be doing). For instance:

var str = "ABCDE";

str = str.replace(/A|B|C|D/g, function(match) {
    var rv;
    switch (match)
    {
        case 'A':
            rv = '1';
            break;
        case 'B':
            rv = '2';
            break;
        case 'C':
            rv = '3';
            break;
        case 'D':
            rv = '4';
            break;
    }
    return rv;
});
alert(str); // Alerts 1234E

(Of course, that particular example would be better done as an array lookup.)

If you're a vertical brevity fiend (I'm not, but some are), you can use early returns:

str = str.replace(/A|B|C|D/g, function(match) {
    switch (match)
    {
        case 'A': return '1';
        case 'B': return '2';
        case 'C': return '3';
        case 'D': return '4';
    }
});
alert(str); // Alerts 1234E

Edit Just to be clear, about my "array lookup" comment above: If the replacements really are just a static lookup, you can do this:

var str, replacements, key, rex;

// Potentially one-time prep, if you're re-using this lookup
replacements = {
    "A": "1",
    "B": "2",
    "C": "3",
    "D": "4"
};
rex = [];
for (key in replacements)
{
    rex.push(key);
}
rex = new RegExp(rex.join('|'), "g");

// The bit you reuse
str = "ABCDE";
str = str.replace(rex, function(match) {
    return replacements[match];
});
alert(str); // Alerts 1234E

...since JavaScript objects are associative arrays.

Sign up to request clarification or add additional context in comments.

3 Comments

Regarding "If you're a vertical brevity fiend" - you can't seriously say that the first example is more readable than the second, can you?
I despise all whitespace, I guess I'd do this then (the second style :P), I was just dreaming of a more concise way to write it. Formatting in the replacement string... makes sense.
@Max: I find it as readable, at least; not less, not more. Trivial examples like the above form a poor basis for debates of readability. :-) You wouldn't do it that way anyway, at least not in JavaScript; you'd use an object (associative array) lookup. But for anything even slightly more complex, I'd absolutely do it the first way. One of the usual maintainability guidelines is to have a single return from a function. It's not a guideline I always follow, but generally, yeah. It makes debugging easier, makes the function less fragile when being enhanced, etc.
0

Why don't you just run them one by one in a loop like so:

for (var i = 0; i < regexes.length; i++) {
    str = str.replace(regexes.regex, regexes.result);
}

It's easy to understand, more or less easy to maintain, and probably faster than one huge query. Those alternatives in regex come to a huge price.

Comments

0

Assuming you want to replace query1 with reslt1, query2 with reslt2, and so on, I don't think that can be done using a single regex. However, it's fairly simply using an Nx2 array (or an object, but the definition of such would be more verbose):

var repl_table = [[/query1/g, 'reslt1'],
                  [/query2/g, 'reslt2'],
                  [/query3/g, 'reslt3'],
                  [/query4/g, 'reslt4'],
                  [/([0-9]+)/g, 'procNumb($1)'],
                  [/([^])/g, 'procChar($1)']]

function repl(s, table) {
  for (var i=0; i<table.length; i++) {
    s = s.replace(table[i][0], table[i][1]);
  }
  return s;
}

// Then call:
result = repl(source, repl_table);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.