Regexp exception in String.replaceAll

T

Tim Slattery

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?
 
A

Arne Vajhøj

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
 
S

Steven Simpson

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)


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.
 
D

Daniele Futtorovic

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:
 
T

Tim Slattery

Read the Javadoc carefully:

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.
 
D

Daniel Pitts

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/doc...tcher.html#quoteReplacement(java.lang.String)>

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

markspace

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(java.lang.String)>
 
D

Daniele Futtorovic

D

Daniel Pitts

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.
 
L

Lew

Tim said:
Daniele Futtorovic said:
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.
 
M

markspace

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!
 
R

Roedy Green

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top