Question: I have a file which looks like:

```
uniprotkb:Q9VNB0|intact:EBI-102551   uniprotkb:A1ZBG6|intact:EBI-195768
uniprotkb:P91682|intact:EBI-142245   uniprotkb:Q24117|intact:EBI-156442
uniprotkb:P92177-3|intact:EBI-204491     uniprotkb:Q9VDK2|intact:EBI-87444

```

and I wish to extract strings between `:` and `|` separators, the output should be:

```
Q9VNB0   A1ZBG6
P91682   Q24117
P92177-3 Q9VDK2

```

tab delimited between the two columns.
I wrote in unix a perl command:

```
perl -l -ne '/:([^|]*)?[^:]*:([^|]*)/ and print($1,"\t",$2)' <file>

```

the output that I got is:

```
Q9VNB0  EBI-102551   uniprotkb:A1ZBG6
P91682  EBI-142245   uniprotkb:Q24117
P92177-3    EBI-204491   uniprotkb:Q9VDK2

```

I wish to know what am I doing wrong and how can I fix the problem.
I don't wish to use split function.

Thanks,

Tom.

Answer: 
The expression you give is too greedy and thus consumes more characters than you wanted. The following expression works on your sample data set:

```
perl -l -ne '/:([^|]*)\|.*:([^|]*)\|/ and print($1,"\t",$2)'

```

It anchors the search with explicit matches for something between a `":"` and `"|"` pair. If your data doesn't match exactly, it *should* ignore the input line, but I have not tested this. I.e., this regex assumes exactly two entries between `":"` and `"|"` will exist per line.
Why do you not want to use the `split` function. On the face of it this would be easily solved by writing

```
my @fields = map /:([^|]+)/, split

```

I am not sure how your regex is supposed to work. Using the `/x` modifier to allow non-significant whitespace it looks like this

```
/ : ([^|]*)? [^:]* : ([^|]*) /x

```

which finds a colon and optionally captures as many non-pipe characters as possible. Then skips over as many non-colon characters as possible to the next colon. Then captures zero asm many non-pipe characters as possible. Because all of your matches are greedy, any one of them is allowed to consume all of the rest of the string as long as the characters match the character class. Note that a `?` that indicates an optional sequence will first of all match all that it can, and the option to skip the sequence will be taken only if the rest of the pattern cannot then be made to match

It is hard to judge from your examples the precise criteria for a field, but this code should do the trick. It finds sequences of characters that are neither a colon nor a pipe that are preceded by a colon and terminated by a pipe

```
use strict;
use warnings;

while (<DATA>) {
  my @fields = /:([^:|]+)\|/g;
  print join("\t", @fields), "\n";
}
__DATA__
uniprotkb:Q9VNB0|intact:EBI-102551   uniprotkb:A1ZBG6|intact:EBI-195768
uniprotkb:P91682|intact:EBI-142245   uniprotkb:Q24117|intact:EBI-156442
uniprotkb:P92177-3|intact:EBI-204491     uniprotkb:Q9VDK2|intact:EBI-87444

```

**output**

```
Q9VNB0  A1ZBG6
P91682  Q24117
P92177-3    Q9VDK2

```