Regular Expression - Match all except last one

Discussion in 'Javascript' started by Randy Webb, Mar 19, 2006.

  1. Randy Webb

    Randy Webb Guest

    I know that the /g flag will match all occurrences. Is there a way, with
    a Regular Expression, to match all occurrences *except* the last one?

    pattern = /df/g;
    var myString = "asdfasdfasdfasdf";
    var newString = myString.replace(pattern,'gh');
    alert(newString)

    Gives me: asghasghasghasgh as it should.
    What I want: asghasghasghasdf Where the last one is not replaced.

    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 19, 2006
    #1
    1. Advertising

  2. Randy Webb

    BootNic Guest

    > "Randy Webb" <> wrote:
    > news:....
    >
    > I know that the /g flag will match all occurrences. Is there a way,
    > with a Regular Expression, to match all occurrences *except* the
    > last one?
    >
    > pattern = /df/g;
    > var myString = "asdfasdfasdfasdf";
    > var newString = myString.replace(pattern,'gh');
    > alert(newString)
    >
    > Gives me: asghasghasghasgh as it should.
    > What I want: asghasghasghasdf Where the last one is not replaced.


    Does the string always end with the pattern?

    --
    BootNic Sunday, March 19, 2006 1:19 AM

    It's not that some people have willpower and some don't. It's that
    some people are ready to change and others are not.
    *James Gordon*
    BootNic, Mar 19, 2006
    #2
    1. Advertising

  3. Randy Webb

    Randy Webb Guest

    BootNic said the following on 3/19/2006 1:20 AM:
    >> "Randy Webb" <> wrote:
    >> news:....
    >>
    >> I know that the /g flag will match all occurrences. Is there a way,
    >> with a Regular Expression, to match all occurrences *except* the
    >> last one?
    >>
    >> pattern = /df/g;
    >> var myString = "asdfasdfasdfasdf";
    >> var newString = myString.replace(pattern,'gh');
    >> alert(newString)
    >>
    >> Gives me: asghasghasghasgh as it should.
    >> What I want: asghasghasghasdf Where the last one is not replaced.

    >
    > Does the string always end with the pattern?
    >


    Yes. And I think I know where you are headed but I will wait and see :)

    The pattern I am actually matching is \r\n and the string is the .value
    of a textarea. It is replacing it with ";\r\ndocument.write("
    Where the " is part of the replacement. All it does is take code and
    create document.write statements for them. What I end up with at the end
    is an extra document.write(" that I don't want.

    I could always just replace the last occurence of document.write(" but I
    was hoping there was a simpler solution.
    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 19, 2006
    #3
  4. Randy Webb

    BootNic Guest

    > "Randy Webb" <> wrote:
    > news:....
    >
    > BootNic said the following on 3/19/2006 1:20 AM:
    >>> "Randy Webb" <> wrote:
    >>> news:....
    >>>
    >>> I know that the /g flag will match all occurrences. Is there a
    >>> way, with a Regular Expression, to match all occurrences *except*
    >>> the last one?
    >>>
    >>> pattern = /df/g;
    >>> var myString = "asdfasdfasdfasdf";
    >>> var newString = myString.replace(pattern,'gh');
    >>> alert(newString)
    >>>
    >>> Gives me: asghasghasghasgh as it should.
    >>> What I want: asghasghasghasdf Where the last one is not replaced.

    >>
    >> Does the string always end with the pattern?
    >>

    >
    > Yes. And I think I know where you are headed but I will wait and
    > see :)
    >
    > The pattern I am actually matching is \r\n and the string is the
    > .value of a textarea. It is replacing it with ";\r\ndocument.write("
    > Where the " is part of the replacement. All it does is take code and
    > create document.write statements for them. What I end up with at
    > the end is an extra document.write(" that I don't want.
    >
    > I could always just replace the last occurence of document.write("
    > but I was hoping there was a simpler solution.


    Well now, I don't think I am comprehending the situation. It sounds like
    you need to strip the the white space on each end of the sting before the
    replace.

    But I don't think that is the issue.

    I was going to suggest one of two things.

    pattern = /df(?=.)/g;
    var myString = "asdfasdfasdfasdf";
    var newString = myString.replace(pattern,'gh');
    alert(newString);

    Or

    var myString = "asdfasdfasdfasdf";
    while(myString.match(/df/g).length!=1){
    myString=myString.replace(/df/,'gh')
    }
    alert(myString);

    --
    BootNic Sunday, March 19, 2006 2:21 AM

    Get your facts first, and then you can distort them as much as you
    please.
    *Mark Twain *
    BootNic, Mar 19, 2006
    #4
  5. Randy Webb wrote:
    > I know that the /g flag will match all occurrences. Is there a way, with
    > a Regular Expression, to match all occurrences *except* the last one?
    >
    > pattern = /df/g;
    > var myString = "asdfasdfasdfasdf";
    > var newString = myString.replace(pattern,'gh');
    > alert(newString)
    >
    > Gives me: asghasghasghasgh as it should.
    > What I want: asghasghasghasdf Where the last one is not replaced.


    var newString = myString.replace(/df(.)/g,'gh$1');

    --
    Alexander Bartolich, Mar 19, 2006
    #5
  6. Randy Webb

    Randy Webb Guest

    Alexander Bartolich said the following on 3/19/2006 4:33 PM:
    > Randy Webb wrote:
    >> I know that the /g flag will match all occurrences. Is there a way, with
    >> a Regular Expression, to match all occurrences *except* the last one?
    >>
    >> pattern = /df/g;
    >> var myString = "asdfasdfasdfasdf";
    >> var newString = myString.replace(pattern,'gh');
    >> alert(newString)
    >>
    >> Gives me: asghasghasghasgh as it should.
    >> What I want: asghasghasghasdf Where the last one is not replaced.

    >
    > var newString = myString.replace(/df(.)/g,'gh$1');


    What do the (.) and $1 do? The code does exactly what I want it to do
    but I want to understand it now.

    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 19, 2006
    #6
  7. JRS: In article <>, dated Sun, 19 Mar
    2006 02:04:22 remote, seen in news:comp.lang.javascript, Randy Webb
    <> posted :

    >The pattern I am actually matching is \r\n and the string is the .value
    >of a textarea. It is replacing it with ";\r\ndocument.write("
    >Where the " is part of the replacement. All it does is take code and
    >create document.write statements for them. What I end up with at the end
    >is an extra document.write(" that I don't want.
    >
    >I could always just replace the last occurence of document.write(" but I
    >was hoping there was a simpler solution.


    Append the string '") ;' and you have effectively neutralised it.

    Or can you pre-process myString with a .replace that removes just the
    final \r\n? Or chop off the last 2 characters with substr or substring?


    OTOH, can you not replace \r\n(.) with ";\r\ndocument.write("$1
    which should not see a final \r\n ? Untested.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
    Dr John Stockton, Mar 19, 2006
    #7
  8. Randy Webb wrote:
    > Alexander Bartolich said the following on 3/19/2006 4:33 PM:
    >> [...]
    >> var newString = myString.replace(/df(.)/g,'gh$1');

    >
    > What do the (.) and $1 do? The code does exactly what I want
    > it to do but I want to understand it now.


    The dot matches any character.
    The round brackets form a parenthesized subexpression.
    The text matched by such subexpression is available in the
    replacement text as $1, $2, $3, etc.

    So what this does is to search for "df" followed by any character,
    and replace that with "gh", followed by that character.

    --
    post tenebras lux. post fenestras tux.
    Alexander Bartolich, Mar 20, 2006
    #8
  9. Randy Webb

    Randy Webb Guest

    Alexander Bartolich said the following on 3/20/2006 3:03 AM:
    > Randy Webb wrote:
    >> Alexander Bartolich said the following on 3/19/2006 4:33 PM:
    >>> [...]
    >>> var newString = myString.replace(/df(.)/g,'gh$1');

    >> What do the (.) and $1 do? The code does exactly what I want
    >> it to do but I want to understand it now.

    >
    > The dot matches any character.
    > The round brackets form a parenthesized subexpression.
    > The text matched by such subexpression is available in the
    > replacement text as $1, $2, $3, etc.
    >
    > So what this does is to search for "df" followed by any character,
    > and replace that with "gh", followed by that character.
    >


    Thank you for the code and the explanation. I guess it's finally time
    for me to read my references on Regular Expressions, asking questions,
    and learn the things.

    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 20, 2006
    #9
  10. Randy Webb

    Randy Webb Guest

    Randy Webb said the following on 3/20/2006 6:58 AM:
    > Alexander Bartolich said the following on 3/20/2006 3:03 AM:
    >> Randy Webb wrote:
    >>> Alexander Bartolich said the following on 3/19/2006 4:33 PM:
    >>>> [...]
    >>>> var newString = myString.replace(/df(.)/g,'gh$1');
    >>> What do the (.) and $1 do? The code does exactly what I want
    >>> it to do but I want to understand it now.

    >>
    >> The dot matches any character.
    >> The round brackets form a parenthesized subexpression.
    >> The text matched by such subexpression is available in the
    >> replacement text as $1, $2, $3, etc.
    >>
    >> So what this does is to search for "df" followed by any character,
    >> and replace that with "gh", followed by that character.
    >>

    >
    > Thank you for the code and the explanation. I guess it's finally time
    > for me to read my references on Regular Expressions, asking questions,
    > and learn the things.
    >


    I think I spoke too soon for it doing exactly what I want it to do. I
    think I gave a bad example with my first question as it doesn't actually
    do what I need it to do in the real scenario.

    This is my actual code:

    var input = document.myForm.textarea1;
    var output = document.myForm.textarea2;
    delim = /\r\n(.)/g;
    output.value = "document.write('" +
    input.value.replace(delim,'\');\ndocument.write\(\'$1');
    output.value = output.value + "');";

    What it does is take the input value of one textarea and create
    document.write statements with every line. It is fine unless there is an
    extra line at the end.

    If the value of textarea1 is:

    test<nothing more>

    Then it works properly and give this in textarea2:

    document.write('test');

    But, if textarea1 looks like this:

    test
    <nothing more>

    Where it has that extra carriage return then the code I get is this:

    document.write('test
    ');

    Which isn't what I want.

    So, how do I deal with that extra line in the textarea?

    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 20, 2006
    #10
  11. Randy Webb

    BootNic Guest

    > "Randy Webb" <> wrote:
    > news:....

    [snip]
    > So, how do I deal with that extra line in the textarea?


    Trim the white space.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <script type="text/javascript">
    function tellerror(msg, url, lnn){
    alert('Error message= '+msg+'\nURL= '+url+'\nLine Number= '+lnn)
    return true
    }
    window.onerror=tellerror
    </script>
    <script type="text/javascript">
    function cod(){
    String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,'')};
    var input = document.myForm.textarea1;
    var output = document.myForm.textarea2;
    delim = /(\r\n)+|(\n)+/g;
    output.value='';
    output.value="document.write('" +
    input.value.trim().replace(delim,'\');\ndocument.write\(\'')+ "');"
    }
    </script>
    <title></title>
    </head>
    <body>
    <form action="javascript:cod()" name="myForm" id="myForm">
    <textarea wrap="off" name="textarea1" cols="25" rows="15">
    First line.






    Second Line.
    Third Line.


    Last Line.



    </textarea>
    <textarea wrap="off" name="textarea2" cols="25" rows="15">
    </textarea> <input type="submit" value="cod">
    </form>
    </body>
    </html>


    --
    BootNic Monday, March 20, 2006 8:24 AM

    Sometimes I think the surest sign that intelligent life exists
    elsewhere in the universe is that none of it has tried to contact us.
    *Bill Watterson*
    BootNic, Mar 20, 2006
    #11
  12. Hi BootNic,

    Great code enhancement. I'm an html/ javascript noobie, so I like
    trolling the Q&As on this newsgroup to learn coding techniques.

    Question: Do you concur in my belief that the preliminary null
    assignment to output.value is superfluous because the succeeding
    assignment completely replaces output.value's content?

    Question: What's a good on-line source for learning the semantics of
    your "String.prototype.trim" assignment statement? I don't mean the RE
    stuff or replacing stings of leading or trailing space characters with
    nulls. I mean:
    - Does String have a property that has a trim method;
    - Or is prototype a generic method to modify any method of any class

    Thanks in advance,
    Richard
    Richard Lionheart, Mar 20, 2006
    #12
  13. Alexander Bartolich <> writes:

    >> Alexander Bartolich said the following on 3/19/2006 4:33 PM:
    >>> [...]
    >>> var newString = myString.replace(/df(.)/g,'gh$1');

    ....
    > So what this does is to search for "df" followed by any character,
    > and replace that with "gh", followed by that character.


    And it will fail on "dfdfdf", replacing only the first one.

    If you expect the regexp engine to be recent, you can use positive
    lookahead:
    /df(?:.)/g
    Then you could also just use negative lookahead on the end of text:
    /df(?!$)/g

    It's quite a lot harder without lookahead, since regular expressions
    are notoriously hard to get to do a negative match (which is what
    "not at the end" is).

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, Mar 20, 2006
    #13
  14. Randy Webb

    BootNic Guest

    > "Richard Lionheart" <> wrote:
    > news:....
    >
    > Hi BootNic,
    >
    > Great code enhancement. I'm an html/ javascript noobie, so I like
    > trolling the Q&As on this newsgroup to learn coding techniques.
    >
    > Question: Do you concur in my belief that the preliminary null
    > assignment to output.value is superfluous because the succeeding
    > assignment completely replaces output.value's content?



    It should not be there, I would guess that I started to type out something
    different then desided to paste instead.

    > Question: What's a good on-line source for learning the semantics of
    > your "String.prototype.trim" assignment statement? I don't mean
    > the RE stuff or replacing stings of leading or trailing space
    > characters with nulls. I mean:
    > - Does String have a property that has a trim method;
    > - Or is prototype a generic method to modify any method of any class



    I would not normally use prototype, I used it this time simply because there
    is something similar in the FAQ. It also should be outside of the function.

    I prefer the Trim(str) function over the prototype. In example I posted,
    a replace(/^\s+|\s$/g,'') in place of trim() would have done well.

    http://jibbering.com/faq/#FAQ4_16

    There is a lot of room for improvement on what I posted.

    for example delim = /(\r\n)+|(\n)+/g; could be written different.

    --
    BootNic Monday, March 20, 2006 3:00 PM

    "This is all very interesting, and I daresay you already see me
    frothing at the mouth in a fit; but no, I am not; I am just winking
    happy thoughts into a little tiddle cup."
    *Nabokov, Lolita*
    BootNic, Mar 20, 2006
    #14
  15. JRS: In article <>, dated Mon, 20 Mar
    2006 07:05:16 remote, seen in news:comp.lang.javascript, Randy Webb
    <> posted :
    >
    >So, how do I deal with that extra line in the textarea?


    You could, maybe, .split the textarea at newlines; then scan the array
    dealing with empty lines (e.g. put only non-empty ones into another
    array, or remove trailing empties), also adding the ...(" and ");
    strings to each element, then rejoin. It's not what you asked for, but
    it might be clearer.

    <URL:http://www.merlyn.demon.co.uk/js-quick.htm> Pack uses this

    function Pak(F) { var S = F.Code.value, L = +F.Len.value, J, Re
    S = S.replace(/(\r?\n){2,}/g, "\u2029") // PS
    S = S.replace(/(\r?\n)/g, " ")
    S = S.replace(/\s+/g, " ").split("\u2029")
    if (L<1) L = F.Len.value = 1
    Re = new RegExp("(.{1," + L + "}) ", "g")
    J = S.length ; while (J--)
    S[J] = (S[J].replace(/^\s+/, "")+" ").replace(Re, "$1\n")
    F.Code.value = S.join("\n") }

    to paragraph-pack textarea Code; but I didn't care about non-visible
    characters in the output. You might get an idea from it. Or suggest an
    improvement.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
    Dr John Stockton, Mar 20, 2006
    #15
  16. Randy Webb

    Randy Webb Guest

    Dr John Stockton said the following on 3/20/2006 6:20 PM:
    > JRS: In article <>, dated Mon, 20 Mar
    > 2006 07:05:16 remote, seen in news:comp.lang.javascript, Randy Webb
    > <> posted :
    >> So, how do I deal with that extra line in the textarea?

    >
    > You could, maybe, .split the textarea at newlines; then scan the array
    > dealing with empty lines (e.g. put only non-empty ones into another
    > array, or remove trailing empties), also adding the ...(" and ");
    > strings to each element, then rejoin. It's not what you asked for, but
    > it might be clearer.


    Ironically enough, that is exactly how I wrote it to start with and a
    thread a few days ago about ABC:DEF: or something like that made me
    start wondering if I could hack together a RegEx solution so I started
    whacking. In the end, I went back to exactly what you suggested (that I
    started out with).

    Uncommented, this is the entire function:

    function convertIt(){
    var output = document.myForm.textarea2;
    var myArray =
    document.myForm.textarea1.value.replace('\'','\\\'').split('\r\n');
    for (var i=0;i<myArray.length;i++)
    if (myArray != '')
    {
    output.value += "document.write('" + myArray + "');\r\n";
    }
    }

    There are a few more things I am going to add to it, such as removing
    double blank spaces, and empty lines with just a space in it. But
    compared to the RegExp solutions so far, the above is - by far - simpler
    and clearer (as you suggested).

    > <URL:http://www.merlyn.demon.co.uk/js-quick.htm> Pack uses this
    >
    > function Pak(F) { var S = F.Code.value, L = +F.Len.value, J, Re
    > S = S.replace(/(\r?\n){2,}/g, "\u2029") // PS
    > S = S.replace(/(\r?\n)/g, " ")
    > S = S.replace(/\s+/g, " ").split("\u2029")
    > if (L<1) L = F.Len.value = 1
    > Re = new RegExp("(.{1," + L + "}) ", "g")
    > J = S.length ; while (J--)
    > S[J] = (S[J].replace(/^\s+/, "")+" ").replace(Re, "$1\n")
    > F.Code.value = S.join("\n") }
    >
    > to paragraph-pack textarea Code; but I didn't care about non-visible
    > characters in the output. You might get an idea from it. Or suggest an
    > improvement.


    I have saved it for future reference but admittedly, my knowledge of
    RegExp's is not such that I could comment on it, mostly ask questions.

    --
    Randy
    comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
    Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
    Randy Webb, Mar 21, 2006
    #16
  17. JRS: In article <>, dated Tue, 21 Mar
    2006 01:15:47 remote, seen in news:comp.lang.javascript, Randy Webb
    <> posted :

    >> <URL:http://www.merlyn.demon.co.uk/js-quick.htm> Pack uses this
    >>
    >> function Pak(F) { var S = F.Code.value, L = +F.Len.value, J, Re


    >> S = S.replace(/(\r?\n){2,}/g, "\u2029") // PS

    PS is IIRC Paragraph-Space, represented by \u2029. Multiple blank lines
    are turned into PS.

    >> S = S.replace(/(\r?\n)/g, " ")

    Remaining newlines are turned into spaces.

    >> S = S.replace(/\s+/g, " ").split("\u2029")

    Whitespace is turned into single-space, and each paragraph becomes an
    array element.

    >> if (L<1) L = F.Len.value = 1

    The minimum line length is one character.

    >> Re = new RegExp("(.{1," + L + "}) ", "g")

    Re matches any number of characters from 1 to L followed by a space, and
    remembers the characters.

    >> J = S.length ; while (J--)

    For each paragraph

    >> S[J] = (S[J].replace(/^\s+/, "")+" ").replace(Re, "$1\n")

    remove leading spaces, add one trailing space[*]; replace, with a
    newline, each occurrence of a space preceded with enough characters[+].

    >> F.Code.value = S.join("\n") }


    Join the paragraphs.


    >> to paragraph-pack textarea Code; but I didn't care about non-visible
    >> characters in the output. You might get an idea from it. Or suggest an
    >> improvement.

    >
    >I have saved it for future reference but admittedly, my knowledge of
    >RegExp's is not such that I could comment on it, mostly ask questions.


    [*] H'mmm - in principle, maybe I should be removing initial trailing
    spaces here. It appears unnecessary.
    [+] That code is right; but I'm not entirely sure why.

    The code of the page is now better; I've added, first,
    S = S.replace(/^\s+|\s+$/g, "") // FAQ 4.15 Trim
    to clean the ends.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
    Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
    The Big-8 newsgroup management is attempting to reorganise its questionable
    practices while retaining an elitist hegemony. Read <URL:news:news.groups>.
    Dr John Stockton, Mar 21, 2006
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VSK
    Replies:
    2
    Views:
    2,267
  2. Derek Basch
    Replies:
    10
    Views:
    567
    Peter Otten
    Jun 17, 2004
  3. John Salerno
    Replies:
    20
    Views:
    819
    John Salerno
    Aug 11, 2006
  4. Replies:
    23
    Views:
    679
  5. Gunther Gunt

    Regular expression: anything except

    Gunther Gunt, Aug 13, 2008, in forum: Ruby
    Replies:
    5
    Views:
    100
    Mark Thomas
    Aug 13, 2008
Loading...

Share This Page