9

I have an array that contains string which may contain whitespaces appended to the end. I need to remove those spaces using perl script. my array will look like this

@array = ("shayam    "," Ram        "," 24.0       ");

I need the output as

@array = ("shayam","Ram","24.0");

I tried with chomp (@array). It is not working with the strings.

brainless
  • 5,698
  • 16
  • 59
  • 82
Raj
  • 757
  • 4
  • 11
  • 22
  • 1
    Duplicate : http://stackoverflow.com/questions/184590/is-there-a-perl-compatible-regular-expression-to-trim-whitespace-from-both-sides, http://stackoverflow.com/questions/2025658/how-do-i-remove-white-space-in-a-perl-string – Zaid Jul 07 '10 at 07:37
  • In given array, every index containing only single string or multiple strings too like @array = ("shayam nice "," Ram "," 24.0 "); ? – Nikhil Jain Jul 07 '10 at 08:04
  • @Zaid: those aren't exact duplicates of this. This is about doing it for a list of values. –  Jul 07 '10 at 08:23
  • @Kinopiko : Not exact duplicates, but the needs revolve around `s#^\s+|\s+$##g` or `s#\s+$##` in some form or another. – Zaid Jul 07 '10 at 09:26

6 Answers6

39

The underlying question revolves around removing leading and trailing whitespace from strings, and has been answered in several threads in some form or another with the following regex substitution (or its equivalent):

s{^\s+|\s+$}{}g foreach @array;

chomping the array will remove only trailing input record separators ("\n" by default). It is not designed to remove trailing whitespaces.

From perldoc -f chomp:

It's often used to remove the newline from the end of an input record when you're worried that the final record may be missing its newline. When in paragraph mode ($/ = ""), it removes all trailing newlines from the string.

...

If you chomp a list, each element is chomped, and the total number of characters removed is returned.

Community
  • 1
  • 1
Zaid
  • 36,680
  • 16
  • 86
  • 155
  • 1
    This is the correct answer. The OP is asking for the elements of the array to be modified inplace, rather than creating a new array. Also, the solutions with capturing, while not incorrect, are bound to be slower. See also perlfaq: http://perldoc.perl.org/perlfaq4.html#How-do-I-strip-blank-space-from-the-beginning%2fend-of-a-string%3f – Sinan Ünür Jul 07 '10 at 14:29
  • The use of the `{}` as delimiter is close to snobbish :-) But to be honest I didn't know it was accepted.. making [this answer](http://stackoverflow.com/questions/5770590/which-characters-can-be-used-as-regular-expression-delimiters) incomplete.. – Déjà vu Feb 25 '13 at 05:04
  • could you or anyone, please, tell me where this syntax with a 'block' (or what it is) before the `foreach` keyword is documented. The perlsyn page doesn't mention this syntax, but it works. – d.k Mar 03 '17 at 23:09
3

The highest rated answer here looked fine but is, IMHO, not as easy to read as it could be. I added a string with internal spaces to show those are not removed.

#!/usr/bin/perl

use strict;
use warnings;

my @array = ("shayam    "," Ram        "," 24.0       ", " foo bar garply  ");

map { s/^\s+|\s+$//g; } @array;

for my $element (@array) {
    print ">$element<\n";
}

The output:

>shayam<
>Ram<
>24.0<
>foo bar garply<
1

How about: @array = map {join(' ', split(' '))} @array;

lkench
  • 11
  • 1
  • While not asked for this also compresses multiple internal spaces as well as trimming leading and trailing spaces and is the most efficient way to do so, according to recipe 1.19, Perl Cookbook, 2nd Edition – lkench Nov 26 '13 at 21:34
1
#!/usr/local/bin/perl -w

use strict;
use Data::Dumper;

my @array=('a ', 'b', '  c');

my @newarray = grep(s/\s*$//g, @array);

print Dumper \@newarray;

The key function here is grep(), everything else is just demo gravy.

Alan Horn
  • 80
  • 1
  • 2
  • 5
    Wouldn't `map` be more appropriate? – el.pescado - нет войне Jul 07 '10 at 07:38
  • map is more complex than is needed here. Since you know that the regex will always return true, whilst at the same time modifying $_, grep is the best choice. All these folks that are going on with these silly foreach loops clearly haven't read the first couple of chapters of any basic perl book. grep is bread and butter for perl :) – Alan Horn Jul 07 '10 at 07:52
  • 2
    (reply to Alan Horn) IMO 'grep' suggests searching for something in a list, 'map' suggests that the whole list will be used, therefore using 'grep' where a 'map' is more appropriate makes the code less immediately readable – plusplus Jul 07 '10 at 08:11
  • I cannot help it if you don't know the language.
    perldoc -f grep
    
    Evaluates the BLOCK or EXPR for each element of LIST (locally
                   setting $_ to each element) and returns the list value consist‐
                   ing of those elements for which the expression evaluated to
                   true.  In scalar context, returns the number of times the
                   expression was true.
    
    in the world of perl, a grep is an extremely well understood function and is used for this precise thing all the time. Map is not (although it could be).
    – Alan Horn Jul 07 '10 at 08:35
  • 3
    i know both grep and map very well, but i am talking about what they *imply* to me at first glance, and consideration of such factors makes code more readable and hence maintainable by others. the definition of grep just confirms this - 'those elements for which the expression evaluated to true' - in this case *all* the elements are returned, so that is unecessary confusion - if i see a grep i start looking for what exactly will be matched by the grep condition, but if i see a map i know that everything will be used from the input list – plusplus Jul 07 '10 at 08:52
  • 1
    and it obviously depends on personal experience as to which is most common, but i've both seen and used map more than grep in 10+ years of Perl – plusplus Jul 07 '10 at 08:53
  • And in 15+ years I've seen grep used a bunch more, so yes, personal choice really :) – Alan Horn Jul 07 '10 at 22:04
  • 2
    Your regexp only strips space off the end, not at the beginning. – Christopher Causer Dec 21 '12 at 12:15
  • 1
    If for one thing the use of *grep* here is inappropriate is because it won't return the strings that don't have trailing spaces. The OP says *strings may have trailing spaces*. – Déjà vu Feb 25 '13 at 04:59
-1
my @res = ();
my $el;

foreach $el (@array) {
   $el =~ /^\s*(.*?)\s*$/;
   push @res, $1;
}

After this, @res will contain your desired elements.

Borealid
  • 95,191
  • 9
  • 106
  • 122
  • 2
    @daxim: You mean because you can read it? I thought Perl was all about freedom of choice. – Borealid Jul 07 '10 at 09:02
  • 2
    Ridiculous. It is just one line with `map` or [`foreach` (as Zaid shows)](http://stackoverflow.com/questions/3192649#3192716), and therefore more readable. `my $el; foreach $el …` is the style of an unversed beginner, everyone else writes `foreach my $el …`. Also, [bicarbonate](http://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it). Sorry, I don't think your answer is that good and deserves its lack of upvotes. – daxim Jul 07 '10 at 11:32
  • 3
    It is unidiomatic because you are capturing unnecessarily and creating a new array by individually pushing elements rather than modifying the elements of the original array inplace as the OP's question states. If a new array is going to be created, use `map`, if elements of the array will be modified inplace, use `for`. – Sinan Ünür Jul 07 '10 at 14:31
-1

I think Borealid's example should be:

my @array = ("shayam "," Ram "," 24.0 ");
foreach my $el (@array) {
   $el =~ s/^\s*(.*?)\s*$/\1/;
}
bohica
  • 5,932
  • 3
  • 23
  • 28
  • "it may throw some surprises if there are spaces within each string". What are the surprises then? – bohica Jul 07 '10 at 07:53
  • 2
    Avoid using `\1` on the RHS of the substitution. Plus, there is no need to capture here. See perlfaq: http://perldoc.perl.org/perlfaq4.html#How-do-I-strip-blank-space-from-the-beginning%2fend-of-a-string%3f and perlre: http://perldoc.perl.org/perlre.html#Warning-on-%5c1-Instead-of-%241 – Sinan Ünür Jul 07 '10 at 14:32