1

I have a string in Perl that is 23 digits long. I need to cut it apart into different pieces. First 2 digits in one variable, next 3 in another variable, next 4 into another variable, etc. Basically the 23 digits needs to end up as 6 separate variables (2,3,4,4,3,7) characters, in that order.

Any ideas how I can cut the string up like this?

daotoad
  • 26,689
  • 7
  • 59
  • 100
jomille
  • 405
  • 12
  • 24
  • 3
    Duplicate of several questions: [In Perl, how can I unpack to several variables?](http://stackoverflow.com/questions/1165099/), [Can I use Perl's unpack to break up a string into vars?](http://stackoverflow.com/questions/1534455/), [Read chunks of data in Perl](http://stackoverflow.com/questions/3144445/) – mob Feb 22 '11 at 20:28
  • 3
    [How do I read fixed length records in Perl](http://stackoverflow.com/questions/407407/), [How can I break apart fixed-width columns in Perl](http://stackoverflow.com/questions/1893830/), [parse fixed width files](http://stackoverflow.com/questions/4911044/), [How can I extract columns from a fixed-width format in Perl?](http://stackoverflow.com/questions/1494611/) – mob Feb 22 '11 at 20:38

5 Answers5

8

There are lots of ways to do it, but the shortest is probably unpack:

my $string = '1' x 23;
my @values = unpack 'A2A3A4A4A3A7', $string;

If you need separate variables, you can use a list assignment:

my ($v1, $v2, $v3, $v4, $v5, $v6) = unpack 'A2A3A4A4A3A7', $string;
cjm
  • 61,471
  • 9
  • 126
  • 175
2

Expanding on Alex's method, rather than specify each start and end, use the list you gave of lengths.

#!/usr/bin/env perl

use strict;
use warnings;

my $string = "abcdefghijklmnopqrstuvw";
my $pos = 0;
my @split = map { 
  my $start = $pos; 
  my $end = $_;
  $pos += $end;
  substr( $string, $start, $end);
} (2,3,4,4,3,7);

print "$_\n" for @split;

This said you probably should look at unpack which is used for fixed width fields. I have no experience with it though.

Joel Berger
  • 20,180
  • 5
  • 49
  • 104
1

You could use a regex, viz:

$string =~ /\d{2}\d{3}\d{4}\d{4}\d{3}\d{7}/

and capture each part by surrounding with brackets ().

You then find each capture in the variables $1, $2 ... or get them all in the returned list

See perldoc perlre

mu is too short
  • 426,620
  • 70
  • 833
  • 800
river
  • 1,508
  • 1
  • 12
  • 17
0

You want to use perldoc substr.

$substring = substr($string, $start, $length);

I'd also use `map' on a list of [start, length] pairs to make your life easier:

$string = "123456789";
@values = map {substr($string, $_->[0], $_->[1])} ([1, 3], [4, 2] , ...);
Alex
  • 5,863
  • 2
  • 29
  • 46
-1

Here's a sub that will do it, using the already discussed unpack.

sub string_slices { 
    my $str = shift;
    return unpack( join( 'A', '', @_ ), $str );
}
Axeman
  • 29,660
  • 2
  • 47
  • 102