views:

166

answers:

5
+2  Q: 

Perl Substitution

hi,

I have a variable which stores the path on Windows. I want to replace all the \ with / in the path.

for eg. $path = C:\Users\scripts.ps1

Am new to Perl and tried something like

$path = s/\\////

But it didnt work. can you please help me out....

+3  A: 

$path =~ s/\\/\//g;

The g at the end replaces each occurence of \ rather than only the first one.

René Nyffenegger
Would be much clearer if you used `!`, `#` or `{}` delimiters. It would also avoid the extra backslash. I suppose it's down to personal preference...
Zaid
+3  A: 

If you use a different pattern delimiter, you don't need to escape the forward slash:

$path =~ s!\\!/!g;
kemp
+4  A: 

For some variety, lets also mention the tr operator

$path =~ tr!\\!/!;

or

$path =~ y!\\!/!;

will replace all instances of \ with / in $path

Hasturkun
+10  A: 

If you want a cross-platform way of doing this, use File::Spec.

($volume,$directories,$file) = File::Spec->splitpath( $path );
@dirs = File::Spec->splitdir( $directories );

Then use catpath to join it back.

codeholic
Upvote for using the right tool for the job.
daxim
+2  A: 

Your attempt was almost right. Let's take a closer look:

$path = s/\\////
             ^

First, to make the substitution operate on the $path variable, you need to use the =~ binding operator, not just the plain assignment operator. Next, since you used the customary slash character as your substitution delimiter, the slash indicated above actually marks the end of the substitution command, and the remaining two slashes are just garbage. It looks like you might have thought that the rule for by-passing the special properties of a character is to double it. If your only example is the backslash, then that rule might make sense, but the rule is actually to prefix special characters with backslashes. Replace that highlighted slash with a backslash, and it becomes the escape character, so we by-pass the special function of the next slash to treat it as a plain slash, allowing the slash after that to properly terminate the substitution:

$path =~ s/\\/\//

But that's hard to read. Luckily, you're not required to use slash as the substitution delimiter; you can use just about any character you want. Choose a delimiter that doesn't resemble the text you're trying to substitute, and your code can be more readable. Details are in perlop under Quote and quote-like operators. When the character you choose forms a pair with another character, you use both to enclose the two parts of the expression. And furthermore, since you probably want to replace all the slashes in your string, you should use the g modifier at the end, telling it to match globally instead of stopping after the first substitution. Bringing it all together:

$path =~ s{\\}{/}g

Since you're substituting a single character for another single character, you can use the more specialized transliteration operator tr instead of s. It automatically applies globally.

$path =~ tr{\\}{/}

Finally, if this is more than just a one-off path operation (i.e., you do this multiple times in the script, or the script will be maintained for a while), or you need your code to run the same on multiple platforms, consider using the File::Spec module. It lets you split and join path components using the right separator for whatever platform you're running on.

Rob Kennedy
@Rob : What about global matching for `s///` ?
Zaid
Thank you, @Zaid. Feel free to make whatever other improvements you wish; that's why I marked my answer as community wiki. (Also because mine is just a summary of the other four answers.)
Rob Kennedy
thanks for the help guys!
Marlin