views:

218

answers:

5

Hi,

if I have a string, say:

my $string = "A, B,C, D , E ";

How can I put this into an array in Perl without the leading and trailing spaces? So what I want is only a single letter in each array element. What I currently do is this:

my @groups = split /,\s*/, $string;

But this is obviously not enough, as the trailing spaces are still there. Any help appreciated. Thanks a lot !!

+7  A: 

Then strip leading/trailing spaces before you split and match the leading/trailing spaces in the split expression.

my $string = " A, B,C, D , E ";
$string =~ s/^\s+//;
$string =~ s/\s+$//;
my @groups = split /\s*,\s*/, $string;

Using a module like Text::CSV is probably better than trying to do your own CSV parsing, though.

jamessan
Drat. Beat me to it. :-)
BlairHippo
That faq talks about the trimming leading/trailing whitespace, so I'm not sure what you're wanting to draw attention to.
jamessan
Unless your input is guaranteed to be this simple, the folks who've steered you towards Text::CSV are right: you don't want to parse it yourself. If there are any commas embedded in the data, this simple split statement will break-up fields it shouldn't.
BlairHippo
@jamessan I think there used to be a caution about `\s*` in that question or maybe I was thinking of something else. I just think your code is doing too much work.
Sinan Ünür
@jamessan I guessed wrong. Your code is about 30% faster than the `split` and `map` strategy.
Sinan Ünür
+2  A: 

Here you go:

@groups = split /,/, $string;
#remove whitespace now.
@groups = map { s/^\s+//; s/\s+$//; $_ } @groups;

Note: the regex can be simplified I'm pretty sure, just haven't worked it out yet.

Paul Nathan
You're all really amazing! This worked really good! Thanks a lot for the help!
Juan
s/// will transform the elements in @groups, therefore this is a useless use of map. You can just do: s/^\s+//, s/\s+$// for @groups;Or use Filter in Algorithm::Loops.
runrig
+5  A: 
my @groups = map { s!^\s+!!; s!\s+$!!; $_ } split /,/, $string;

or

my @groups = $string =~ /([A-Z])/g;

However, unless the input is really as simple as you have shown, you would be better off using Text::CSV or Text::xSV.

Sinan Ünür
Why are you using ! as a q{} delimiter, out of curiosity?
Paul Nathan
@Paul Nathan: Because I get very annoyed that SO treats the trailing `//` in `s/\s+$//` as a comment character and grays out the rest of the line.
Sinan Ünür
@Sinan: makes sense! It annoys me too.
Paul Nathan
@FM: That alternation is notoriously slow. Don't do it in one s///.
brian d foy
See my map comment on Paul Nathan's answer.
runrig
+1  A: 

Just to make sure I'm not missing something, after trying to demystify your examples, I came up with this:

my $string = " A, B,C, D , E ";
$string =~ s/\s+//g;
my @groups = split /,/, $string;

Would work either I guess?

Juan
This removes ALL whitespace, not just whitespace around commas and at the beginning/end of line. For example, if you have $string = " Bob Jones, George Jetson, Foo Bar" then your code strips the spaces between the words too.
jamessan
+2  A: 

You don't have to limit yourself to split, you just use a match with the /g modifier.

my $string = " A, B,C, D , E ";
my @groups = $string =~ /\s*([^,]+?)\s*,?/g;
Brad Gilbert