Regexp exception in String.replaceAll

Discussion in 'Java' started by Tim Slattery, Sep 26, 2012.

  1. Tim Slattery

    Tim Slattery Guest

    I'm getting an "IndexOutOfBoundsException" from the regex processor
    when I call String.replaceAll.

    Here's the call:

    String result = upload.replaceAll("\\{FileName\\}", fileName);

    "upload" is a string that contains at least one occurrence of
    "{FileName}", which is to be replaced by the actual filename passed
    into this method. Unfortunately, I don't know what the filename was
    when the exception occurred. The stacktrace looks like this:

    java.lang.IndexOutOfBoundsException: No group 5
    at java.util.regex.Matcher.group(Matcher.java:470)
    at java.util.regex.Matcher.appendReplacement(Matcher.java:737)
    at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    at java.lang.String.replaceAll(String.java:2189)
    at (the line shown above)

    I'm aware that replaceAll uses the regexp mechanism for matching
    strings. But I can't imagine what could cause this exception. Does
    anybody have a clue?

    --
    Tim Slattery
     
    Tim Slattery, Sep 26, 2012
    #1
    1. Advertising

  2. Tim Slattery

    Arne Vajhøj Guest

    On 9/26/2012 8:57 AM, Tim Slattery wrote:
    > I'm getting an "IndexOutOfBoundsException" from the regex processor
    > when I call String.replaceAll.
    >
    > Here's the call:
    >
    > String result = upload.replaceAll("\\{FileName\\}", fileName);
    >
    > "upload" is a string that contains at least one occurrence of
    > "{FileName}", which is to be replaced by the actual filename passed
    > into this method. Unfortunately, I don't know what the filename was
    > when the exception occurred. The stacktrace looks like this:
    >
    > java.lang.IndexOutOfBoundsException: No group 5
    > at java.util.regex.Matcher.group(Matcher.java:470)
    > at java.util.regex.Matcher.appendReplacement(Matcher.java:737)
    > at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    > at java.lang.String.replaceAll(String.java:2189)
    > at (the line shown above)
    >
    > I'm aware that replaceAll uses the regexp mechanism for matching
    > strings. But I can't imagine what could cause this exception. Does
    > anybody have a clue?


    There are no reason why that replaceAll should try and access group 5.

    I suspect the exception comes from a different line.

    Arne
     
    Arne Vajhøj, Sep 26, 2012
    #2
    1. Advertising

  3. On 26/09/12 13:57, Tim Slattery wrote:
    > java.lang.IndexOutOfBoundsException: No group 5
    > at java.util.regex.Matcher.group(Matcher.java:470)
    > at java.util.regex.Matcher.appendReplacement(Matcher.java:737)
    > at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    > at java.lang.String.replaceAll(String.java:2189)
    > at (the line shown above)


    $ cat Replace.java
    public class Replace {
    public static void main(String[] args) throws Exception {
    String upload = "oof flange {FileName} dangle";
    String fileName = "wart$5x";
    String result = upload.replaceAll("\\{FileName\\}", fileName);
    System.err.println(result);
    }
    }
    $ javac Replace.java
    $ java Replace
    Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 5
    at java.util.regex.Matcher.start(Matcher.java:374)
    at java.util.regex.Matcher.appendReplacement(Matcher.java:831)
    at java.util.regex.Matcher.replaceAll(Matcher.java:906)
    at java.lang.String.replaceAll(String.java:2162)
    at Replace.main(Replace.java:5)


    <http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29>:
    > Note that backslashes (\) and dollar signs ($) in the replacement
    > string may cause the results to be different than if it were being
    > treated as a literal replacement string


    So you probably had a "$5" in your fileName somewhere.


    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Sep 26, 2012
    #3
  4. On 26/09/2012 14:57, Tim Slattery allegedly wrote:
    > I'm getting an "IndexOutOfBoundsException" from the regex processor
    > when I call String.replaceAll.
    >
    > Here's the call:
    >
    > String result = upload.replaceAll("\\{FileName\\}", fileName);
    >
    > "upload" is a string that contains at least one occurrence of
    > "{FileName}", which is to be replaced by the actual filename passed
    > into this method. Unfortunately, I don't know what the filename was
    > when the exception occurred. The stacktrace looks like this:
    >
    > java.lang.IndexOutOfBoundsException: No group 5
    > at java.util.regex.Matcher.group(Matcher.java:470)
    > at java.util.regex.Matcher.appendReplacement(Matcher.java:737)
    > at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    > at java.lang.String.replaceAll(String.java:2189)
    > at (the line shown above)
    >
    > I'm aware that replaceAll uses the regexp mechanism for matching
    > strings. But I can't imagine what could cause this exception. Does
    > anybody have a clue?
    >


    Read the Javadoc carefully:

    <http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29>
    > Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string; see Matcher.replaceAll. Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired.


    --
    DF.
     
    Daniele Futtorovic, Sep 26, 2012
    #4
  5. Tim Slattery

    Tim Slattery Guest

    Daniele Futtorovic <> wrote:


    >Read the Javadoc carefully:
    >
    ><http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29>
    >> Note that backslashes (\) and dollar signs ($) in the replacement
    >> string may cause the results to be different than if it were being
    >> treated as a literal replacement string; see Matcher.replaceAll. Use
    >> Matcher.quoteReplacement(java.lang.String) to suppress the special
    >> meaning of these characters, if desired.


    Yes, I had completely missed that. I thought it was a literal
    replacement string.

    In JSE4 and 5 the "replace" method took arguments of type "char". Now
    I see that in JSE6 those arguments are CharSequence, an interface
    which String implements. So before JSE6, if you needed String
    arguments, you had a choice of ReplaceAll or ReplaceFirst. Since I
    needed to allow for multiple occurrences of the replace string, I had
    to use ReplaceAll, and I missed this trap. (And I never considered
    that anybody would use a dollar sign in a filename!). Now that we're
    using JSE6, I can just change it to call replace instead of
    replaceAll.

    --
    Tim Slattery
     
    Tim Slattery, Sep 26, 2012
    #5
  6. Tim Slattery

    Daniel Pitts Guest

    On 9/26/12 5:57 AM, Tim Slattery wrote:
    > I'm getting an "IndexOutOfBoundsException" from the regex processor
    > when I call String.replaceAll.
    >
    > Here's the call:
    >
    > String result = upload.replaceAll("\\{FileName\\}", fileName);
    >
    > "upload" is a string that contains at least one occurrence of
    > "{FileName}", which is to be replaced by the actual filename passed
    > into this method. Unfortunately, I don't know what the filename was
    > when the exception occurred. The stacktrace looks like this:
    >
    > java.lang.IndexOutOfBoundsException: No group 5
    > at java.util.regex.Matcher.group(Matcher.java:470)
    > at java.util.regex.Matcher.appendReplacement(Matcher.java:737)
    > at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    > at java.lang.String.replaceAll(String.java:2189)
    > at (the line shown above)
    >
    > I'm aware that replaceAll uses the regexp mechanism for matching
    > strings. But I can't imagine what could cause this exception. Does
    > anybody have a clue?
    >

    if the fileName variable contains a '\' followed by a '5' perhaps?

    You should be escaping both the replacement and the search term.

    See Matcher.quoteReplacement(String) and Pattern.quote(String):

    <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#quoteReplacement(java.lang.String)>

    <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#quote(java.lang.String)>
     
    Daniel Pitts, Sep 26, 2012
    #6
  7. Tim Slattery

    markspace Guest

    On 9/26/2012 9:35 AM, Tim Slattery wrote:
    > So before JSE6, if you needed String
    > arguments, you had a choice of ReplaceAll or ReplaceFirst. Since I
    > needed to allow for multiple occurrences of the replace string, I had
    > to use ReplaceAll, and I missed this trap. (And I never considered
    > that anybody would use a dollar sign in a filename!). Now that we're
    > using JSE6, I can just change it to call replace instead of
    > replaceAll.



    Just to be a little pendantic here, I'm pretty sure that the "new"
    String::replace just calls Pattern.quote before calling
    String.replaceAll/First. Pattern.quote has been around since Java 1.5,
    so it's not really new.

    <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#quote%28java.lang.String%29>
     
    markspace, Sep 26, 2012
    #7
  8. On 26/09/2012 19:00, markspace allegedly wrote:
    > On 9/26/2012 9:35 AM, Tim Slattery wrote:
    >> So before JSE6, if you needed String
    >> arguments, you had a choice of ReplaceAll or ReplaceFirst. Since I
    >> needed to allow for multiple occurrences of the replace string, I had
    >> to use ReplaceAll, and I missed this trap. (And I never considered
    >> that anybody would use a dollar sign in a filename!). Now that we're
    >> using JSE6, I can just change it to call replace instead of
    >> replaceAll.

    >
    >
    > Just to be a little pendantic here, I'm pretty sure that the "new"
    > String::replace just calls Pattern.quote before calling
    > String.replaceAll/First. Pattern.quote has been around since Java 1.5,
    > so it's not really new.
    >
    > <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#quote%28java.lang.String%29>


    To be a little pedantic myself and for the record, I don't think the
    quoting of a Pattern and the quoting of a replacement string are the
    same type of quoting.

    --
    DF.
     
    Daniele Futtorovic, Sep 26, 2012
    #8
  9. Tim Slattery

    Daniel Pitts Guest

    On 9/26/12 12:26 PM, Daniele Futtorovic wrote:
    > On 26/09/2012 19:00, markspace allegedly wrote:
    >> On 9/26/2012 9:35 AM, Tim Slattery wrote:
    >>> So before JSE6, if you needed String
    >>> arguments, you had a choice of ReplaceAll or ReplaceFirst. Since I
    >>> needed to allow for multiple occurrences of the replace string, I had
    >>> to use ReplaceAll, and I missed this trap. (And I never considered
    >>> that anybody would use a dollar sign in a filename!). Now that we're
    >>> using JSE6, I can just change it to call replace instead of
    >>> replaceAll.

    >>
    >>
    >> Just to be a little pendantic here, I'm pretty sure that the "new"
    >> String::replace just calls Pattern.quote before calling
    >> String.replaceAll/First. Pattern.quote has been around since Java 1.5,
    >> so it's not really new.
    >>
    >> <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#quote%28java.lang.String%29>

    >
    > To be a little pedantic myself and for the record, I don't think the
    > quoting of a Pattern and the quoting of a replacement string are the
    > same type of quoting.
    >

    Indeed, Pattern.quote is for quoting the pattern, and
    Matcher.quoteReplacement is for quoting the replacement. The OP should
    be using both.
     
    Daniel Pitts, Sep 26, 2012
    #9
  10. Tim Slattery

    Lew Guest

    Tim Slattery wrote:
    > Daniele Futtorovic <> wrote:
    >>Read the Javadoc carefully:

    >
    > Yes, I had completely missed that. I thought it was a literal
    > replacement string.
    >
    > In JSE4 [sic] and 5 the "replace" method took arguments of type "char". Now


    Still does in Java 6 and 7.
    http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char, char)
    http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replace(char, char)

    > I see that in JSE6 those arguments are CharSequence, an interface


    Same as in Java 5.
    http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#replace(java.lang.CharSequence, java.lang.CharSequence)

    > which String implements. So before JSE6, if you needed String
    > arguments, you had a choice of ReplaceAll [sic] or ReplaceFirst [sic]. Since I


    The behavior of 'String#replaceAll()' has not changed. It always took regexes.
    http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#replaceAll(java.lang.String, java.lang.String)

    > needed to allow for multiple occurrences of the replace string, I had
    > to use ReplaceAll [sic], and I missed this trap. (And I never considered


    It hasn't changed, ever.

    > that anybody would use a dollar sign in a filename!). Now that we're


    Really?

    It's quite routine, and Java programmers should find it especially common.

    > using JSE6, I can just change it to call replace instead of
    > replaceAll.


    Since those methods work *exactly* the same as in Java 5, I'm not sure
    what you're telling us here.

    --
    Lew
     
    Lew, Sep 26, 2012
    #10
  11. Tim Slattery

    markspace Guest

    On 9/26/2012 1:27 PM, Daniel Pitts wrote:

    > On 9/26/12 12:26 PM, Daniele Futtorovic wrote:
    >> To be a little pedantic myself and for the record, I don't think the
    >> quoting of a Pattern and the quoting of a replacement string are the
    >> same type of quoting.


    > Indeed, Pattern.quote is for quoting the pattern, and
    > Matcher.quoteReplacement is for quoting the replacement. The OP should
    > be using both.



    Nope that's what I get for not paying close attention to what's being
    discussed. Correct on both counts!
     
    markspace, Sep 26, 2012
    #11
  12. Tim Slattery

    Roedy Green Guest

    On Wed, 26 Sep 2012 08:57:53 -0400, Tim Slattery <>
    wrote, quoted or indirectly quoted someone who said :

    >String result = upload.replaceAll("\\{FileName\\}", fileName);


    In the Javadoc for replaceAll is warns you:
    Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
    the replacement string may cause the results to be different than if
    it were being treated as a literal replacement string; see
    {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}.
    Use {@link java.util.regex.Matcher#quoteReplacement} to suppress
    the special meaning of these characters, if desired.
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    The iPhone 5 is a low end Rolex.
     
    Roedy Green, Sep 27, 2012
    #12
    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. sfu
    Replies:
    6
    Views:
    18,550
  2. Mladen Adamovic
    Replies:
    0
    Views:
    759
    Mladen Adamovic
    Dec 4, 2003
  3. Mladen Adamovic
    Replies:
    3
    Views:
    14,697
    Mladen Adamovic
    Dec 5, 2003
  4. Peebster_99
    Replies:
    5
    Views:
    18,943
    Mladen Adamovic
    Mar 7, 2004
  5. Joao Silva
    Replies:
    16
    Views:
    383
    7stud --
    Aug 21, 2009
Loading...

Share This Page