0

I have a string str a\tb\tc\td\te

I want the 1st field value a to go in a variable, then 2nd field value b to go in other variable, then both c\td to go in 3rd variable and last field value e to go in one variable.

If I do

my ($a,$b,$c,$d) = split(/\t/,$_,4);

$c will acquire only c and $d will acquire d\te

I can do:

my ($a,$b,$c) = split(/\t/,$_,3);

Then c will get c\td\te and I can somehow (How?) get rid of last value and get it in $d

How to achieve this?

j08691
  • 204,283
  • 31
  • 260
  • 272
xyz
  • 8,607
  • 16
  • 66
  • 90

2 Answers2

5

split is good when you're keeping the order. If you're breaking the ordering like this you have a bit of a problem. You have two choices:

  1. split according to \t and then join the ones you want.
  2. be explicit.

an example of the first choice is:

my ($a,$b,$c1, $c2, $d) = split /\t/, $_;
my $c = "$c1\t$c2";

an example of the second choice is:

my ($a, $b, $c, $d) = (/(.*?)\t(.*?)\t(.*?\t.*?)\t(.*?)/;

each set of parentheses captures what you want exactly. Using the non-greedy modifier (?) after the * ensures that the parentheses won't capture \t.


Edit: if the intent is to have an arbitrary number of variables, you're best off using an array:

my @x = split /\t/, $_;

my $a = $x[0];
my $b = $x[1];
my $c = join "\t", @x[2..($#x-1)];
my $d = $x[-1];
Joel Berger
  • 20,180
  • 5
  • 49
  • 104
Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
  • +1 for splitting and joining, most simple and readable solution. – heijp06 Nov 28 '11 at 10:32
  • Actually, my real requirement was that, last but one variable should get everything except the last value (and except for first initial 2 values). So there can be more than 2 values. Command should be able to recognize that. – xyz Nov 28 '11 at 11:23
  • ok it is working if I swap he order of arguments in join..thanks. – xyz Nov 28 '11 at 17:03
  • 1
    timtowtdi: `my $a = shift @x; my $b = shift @x; my $d = pop @x; $c = join "\t", @x;` note that this is only useful if this is the only use of `@x` the 0, 1 and -1 elements are removed. – Joel Berger Nov 29 '11 at 03:02
1

You can use a regex with a negative look-ahead assertion, e.g.:

my @fields = split /\t(?!d)/, $string;
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378