7

I am having a lot of trouble doing a simple search and replace. I tried the solution offered in How do I remove white space in a Perl string? but was unable to print this.

Here is my sample code:

#!/usr/bin/perl
use strict;
my $hello = "hello world";
print "$hello\n"; #this should print out >> hello world
#now i am trying to print out helloworld (space removed)
my $hello_nospaces = $hello =~ s/\s//g;
#my $hello_nospaces = $hello =~ s/hello world/helloworld/g;
#my $hello_nospaces = $hello =~ s/\s+//g;
print "$hello_nospaces\n"
#am getting a blank response when i run this.

I tried a couple of different ways, but I was unable to do this.

My end result is to automate some aspects of moving files around in a linux environment, but sometimes the files have spaces in the name, so I want to remove the space from the variable.

Community
  • 1
  • 1
M Alhassan
  • 81
  • 1
  • 1
  • 6
  • 1
    On an unrelated note, linux and many other operating systems support spaces in filenames completely, as long as developers are careful. Removing spaces may have adverse effects, such as creating ambiguities between the files "helloworld.txt" and "hello world.txt". – Rob I Jun 26 '13 at 21:05
  • 1
    thank you all for the quick responses. i kept trying to change the syntax between s and g. sorry i can't vote up, i do not have 15 rep points – M Alhassan Jun 26 '13 at 21:08

4 Answers4

19

You're almost there; you're just confused about operator precedence. The code you want to use is:

(my $hello_nospaces = $hello) =~ s/\s//g;

First, this assigns the value of the variable $hello to the variable $hello_nospaces. Then it performs the substitution operation on $hello_nospaces, as if you said

my $hello_nospaces = $hello;
$hello_nospaces =~ s/\s//g;

Because the bind operator =~ has higher precedence than the assignment operator =, the way you wrote it

my $hello_nospaces = $hello =~ s/\s//g;

first performs the substitution on $hello and then assigns the result of the substitution operation (which is 1 in this case) to the variable $hello_nospaces.

mob
  • 117,087
  • 18
  • 149
  • 283
  • Thank you very much. I thought it was a syntax error alone. your explanation was very clear and now i understand. Thank you – M Alhassan Jun 26 '13 at 21:14
  • 1
    It's pretty clear the op was not having a precedence problem--instead the op was having an in-place-substitution problem, i.e. the op believed s// returned a new string. – 7stud Jun 27 '13 at 08:32
9

As of 5.14, Perl provides a non-destructive s/// option:

Non-destructive substitution

The substitution (s///) and transliteration (y///) operators now support an /r option that copies the input variable, carries out the substitution on the copy, and returns the result. The original remains unmodified.

my $old = "cat";
my $new = $old =~ s/cat/dog/r;
# $old is "cat" and $new is "dog"

This is particularly useful with map. See perlop for more examples.

So:

my $hello_nospaces = $hello =~ s/\s//gr;

should do what you want.

Community
  • 1
  • 1
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
4

You just need to add parentheses so Perl's parser can understand what you want it to do.

my $hello = "hello world";
print "$hello\n";

to

(my $hello_nospaces = $hello) =~ s/\s//g;
print "$hello_nospaces\n";

## prints 
## hello world
## helloworld
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
3

Split this line:

my $hello_nospaces = $hello =~ s/\s//g;

Into those two:

my $hello_nospaces = $hello;
$hello_nospaces =~ s/\s//g;

From the official Perl Regex Tutorial:

If there is a match, s/// returns the number of substitutions made; otherwise it returns false.

Vladimir Georgiev
  • 1,949
  • 23
  • 26
  • 4
    Or `(my $hello_nospaces = $hello) =~ s/\s//g;`. Not sure why I prefer this but it's a little shorter. – Rob I Jun 26 '13 at 21:01