[groovy-user] replacing backslashes per pattern in a string

458 views
Skip to first unread message

Detering Dirk

unread,
Mar 14, 2008, 11:07:38 AM3/14/08
to us...@groovy.codehaus.org
Hello all,

what is the correct way to replace backslashes
in a string representing a DOS path with single slashes?

Trying to use path.replaceAll(/\/, "/") does not work.


(BTW: The error message is:
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed, PluginErrorCheck.groovy: 9: expecting anything but '
'\n''; got it anyway @ line 9, column 34.
println x.replaceAll(/\/, "/")
The column hints to different places after replaceAll depending
on the other code around this method call in the same line.)

Use double backslashes in the expression gives the same result.

The only solution I got to work is to use normal strings and
use four(!) backslashes in the regex:
println x.replaceAll("\\\\", "/")

Even the trick mentioned in GinA in the footnote on p. 70
does not work, it needs to be:
def regex = /${'\\\\'}/

When you only do:
def regex = /${'\\'}/
and call
println x.replaceAll(regex, "/")
you get:
Caught: java.util.regex.PatternSyntaxException:
Unexpected internal error near index 1
\
^

No way around that?

KR
Det
--
ISKV
Paul-Klinger-Straße 15
45127 Essen
Telefon +49-(0)-201-1094-436
Fax +49-(0)-201-1094-444
< http://www.iskv.de/>


***********************************************************************

Die Information in dieser email ist vertraulich und ist ausschließlich
für den/die benannten Adressaten bestimmt. Ein Zugriff auf diese
email durch andere Personen als den/die benannten Adressaten ist
nicht gestattet. Sollten Sie nicht der benannte Adressat sein, löschen
Sie bitte diese email.

***********************************************************************

ARGE Informationssysteme
in der gesetzlichen Krankenversicherung GmbH
Paul-Klinger-Straße 15, 45127 Essen

Amtsgericht Essen HRB 11122
Vorsitzender des Aufsichtsrates: Wolfgang Schmeinck
Geschäftsführer: Gernot Kiefer


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Paul King

unread,
Mar 14, 2008, 7:32:42 PM3/14/08
to us...@groovy.codehaus.org
Detering Dirk wrote:
> Hello all,
>
> what is the correct way to replace backslashes
> in a string representing a DOS path with single slashes?
>
> Trying to use path.replaceAll(/\/, "/") does not work.

Yes, you can't have a backslash as the last character
of a slashy string because it is the escape character
for putting backslashes into the string. So what you
had was correct unless you want to not use regexs:

def x = /C:\Windows\Temp/


println x.replaceAll('\\\\', '/')

println new File(x).toURI().toString() - 'file:/'

Paul.

Detering Dirk

unread,
Mar 18, 2008, 4:30:48 AM3/18/08
to us...@groovy.codehaus.org
Hello,

thanks Paul,



> > what is the correct way to replace backslashes in a string
> > representing a DOS path with single slashes?
> >
> > Trying to use path.replaceAll(/\/, "/") does not work.
>
> Yes, you can't have a backslash as the last character of a
> slashy string because it is the escape character for putting
> backslashes into the string.

The problem occured when peer-reviewing a committed source and
was slightly obscured as my question rendered my own tests.

Did a test today on another machine having groovy 1.0 installed
(like the original committer had), so the real problem was hidden
in a side note in my text:

> > Use double backslashes in the expression gives the same result.


So here is a test, checked in GroovyConsole:

Version 1.0:

groovy> x = "D:\\this\\is\\a\\file"
groovy> println x
groovy> r = x.replaceAll(/\\/, "/")
groovy> println r

D:\this\is\a\file
D:/this/is/a/file

Version 1.5.4:

groovy> x = "D:\\this\\is\\a\\file"
groovy> println x
groovy> r = x.replaceAll(/\\/, "/")
groovy> println r

Exception thrown:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup
failed, Script1: 3: expecting anything but ''\n''; got it anyway @ line
3, column 28.
1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup
failed, Script1: 3: expecting anything but ''\n''; got it anyway @ line
3, column 28.
1 error


Code breaking change with 1.5 or subject for a JIRA issue?

KR
Det


***********************************************************************

Die Information in dieser email ist vertraulich und ist ausschliesslich
fuer den/die benannten Adressaten bestimmt. Ein Zugriff auf diese


email durch andere Personen als den/die benannten Adressaten ist

nicht gestattet. Sollten Sie nicht der benannte Adressat sein, loeschen
Sie bitte diese email.

***********************************************************************

ARGE Informationssysteme
in der gesetzlichen Krankenversicherung GmbH

Paul-Klinger-Strasse 15, 45127 Essen


Amtsgericht Essen HRB 11122
Vorsitzender des Aufsichtsrates: Wolfgang Schmeinck

Geschaeftsfuehrer: Gernot Kiefer

Paul King

unread,
Mar 18, 2008, 5:22:58 AM3/18/08
to us...@groovy.codehaus.org

This was changed in 1.5. The example above still has a backslash as
the last character of a slashy string which isn't allowed. In 1.0 you
weren't allowed to have an odd number of backslashes anywhere in the
slashy string.

Paul.

> KR
> Det

Detering Dirk

unread,
Mar 18, 2008, 7:04:10 AM3/18/08
to us...@groovy.codehaus.org
Hello Paul,

> > groovy> x = "D:\\this\\is\\a\\file"
> > groovy> println x
> > groovy> r = x.replaceAll(/\\/, "/")
> > groovy> println r
> >
> > D:\this\is\a\file
> > D:/this/is/a/file

[...]


> This was changed in 1.5. The example above still has a
> backslash as the last character of a slashy string which
> isn't allowed.

VERY annoying. The 1.5 behaviour is not groovy when scripting
a windose machine, where you often have to replace the
unfortunate backslash in pathes. Most typical application for
replace with pattern AFAIC.

The behaviour of 1.0 (same as Ruby's x.gsub(/\\/, "/") btw )
was a convenient, for every one intuitive way.

> In 1.0 you weren't allowed to have an odd
> number of backslashes anywhere in the slashy string.

Quite understandable. But there isn't an odd number in the
mentioned commited solution, which was coded like to be seen
above.

NB: Such changes make it hard to be a Groovy evangelist
in my company ... :-( .

The question came:
Do we have to factor out such simple things and unit test them?
Say: Do we have to unit test Groovy itsself to save our implementations?

Just my 2ct
KR
Det


***********************************************************************

Die Information in dieser email ist vertraulich und ist ausschliesslich
fuer den/die benannten Adressaten bestimmt. Ein Zugriff auf diese
email durch andere Personen als den/die benannten Adressaten ist
nicht gestattet. Sollten Sie nicht der benannte Adressat sein, loeschen
Sie bitte diese email.

***********************************************************************

ARGE Informationssysteme
in der gesetzlichen Krankenversicherung GmbH
Paul-Klinger-Strasse 15, 45127 Essen

Amtsgericht Essen HRB 11122
Vorsitzender des Aufsichtsrates: Wolfgang Schmeinck
Geschaeftsfuehrer: Gernot Kiefer

Paul King

unread,
Mar 18, 2008, 7:50:22 AM3/18/08
to us...@groovy.codehaus.org

Well, there was a big debate on the mailing list and eventually
we decided to make the change. There were several broken things
about the old way of doing things.

You couldn't have strings like /C:\this\is\a\file/ because
it has 4 occurrences of an odd number of backslashes. You
also couldn't have slashes in slashy strings. What if my original
string had 1, 3, 5, 7, ... backslashes. There would be no way to
get rid of those. You couldn't have .replaceAll(/\\\/, 'X') because
that has an odd number of backslashes.

In the end, we thought there were enough workarounds for cases
were you might have a backslash at the end of a slashy string:

x = /C:\this\is\a\file/
println x
// ----------------------
r = x.replaceAll(/\\${''}/, "/")
println r
// ----------------------
e = ''
r = x.replaceAll(/\\$e/, "/")
println r
// ----------------------
r = x.replaceAll('\\\\', "/")
println r
// ----------------------
r = new File(x).toURI().toString() - 'file:/'
println r
// ----------------------
r = x.tokenize('\\').join('/')
println r
// ----------------------
String.metaClass.gsub = { from, to ->
delegate.tokenize(from).join(to)
}
r = x.gsub('\\', '/')
println r
// ----------------------

It isn't perfect but it was the best that the mailing list
could come up with at the time.

Paul.


> The question came:
> Do we have to factor out such simple things and unit test them?
> Say: Do we have to unit test Groovy itsself to save our implementations?
>
> Just my 2ct
> KR
> Det

Detering Dirk

unread,
Mar 18, 2008, 10:02:55 AM3/18/08
to us...@groovy.codehaus.org
Hello Paul,

thank you for your explanation and the list of workarounds.

I indeed like this for its similar expressiveness:


> r = x.tokenize('\\').join('/')

[...]


> r = x.gsub('\\', '/')

Well, this gsub thing as part of the GDK String extension
seems attractive ... too useful for a handmade metaclass
enhancement.

(What shall I say now? Don't switch languages too often and
know the APIs better ;-) ).

KR
Det


***********************************************************************

Die Information in dieser email ist vertraulich und ist ausschliesslich
fuer den/die benannten Adressaten bestimmt. Ein Zugriff auf diese
email durch andere Personen als den/die benannten Adressaten ist
nicht gestattet. Sollten Sie nicht der benannte Adressat sein, loeschen
Sie bitte diese email.

***********************************************************************

ARGE Informationssysteme
in der gesetzlichen Krankenversicherung GmbH
Paul-Klinger-Strasse 15, 45127 Essen

Amtsgericht Essen HRB 11122
Vorsitzender des Aufsichtsrates: Wolfgang Schmeinck
Geschaeftsfuehrer: Gernot Kiefer

Reply all
Reply to author
Forward
0 new messages