user1939168
user1939168

Reputation: 557

Replace single space with multiple spaces in perl

I have a requirement of replacing a single space with multiple spaces so that the second field always starts at a particular position (here 36 is the position of second field always). I have a perl script written for this:

while(<INP>)
{
my $md=35-index($_," ");
my $str;
$str.=" " for(1..$md);
$_=~s/ +/$str/;
print "$_" ;
}

Is there any better approach with just using the regex in =~s/// so that I can use it on CLI directly instead of script.

Upvotes: 2

Views: 332

Answers (2)

zdim
zdim

Reputation: 66899

Assuming that the fields in your data are demarcated by spaces

while (<$fh>) {
    my ($first, @rest) = split;
    printf "%-35s @rest\n", $first;
}

The first field is now going to be 36 wide, aligned left due to - in the format of printf. See sprintf for the many details. The rest is printed with single spaces between the original space-separated fields, but can instead be done as desired (tab separated, fixed width...).

Or you can leave the "rest" after the first field untouched by splitting the line into two parts

while (<$fh>) {
    my ($first, $rest) = /(\S+)\s+(.*)/;
    printf "%-35s $rest\n", $first;
}

(or use split ' ', $_, 2 instead of regex)

Please give more detail if there are other requirements.

Upvotes: 3

Stefan Becker
Stefan Becker

Reputation: 5962

One approach is to use plain ol' Perl formats:

#!/usr/bin/perl
use warnings;
use strict;

my($first, $second, $remainder);
format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$first,                            $second,$remainder
.

while (<DATA>) {
    ($first, $second, $remainder) = split(/\s+/, $_, 3);
    write;
}

exit 0;

__DATA__
ABCD TEST EFGH don't touch
FOO      BAR    FUD don't touch

Test output. I probably miscounted the columns, but you should get the idea:

$ perl dummy.pl
ABCD                               TEST    EFGH don't touch
FOO                                BAR     FUD don't touch

Other option would be Text::Table

Upvotes: 2

Related Questions