开发者

How do I match none, one or two value in one string?

I have a string which can include none, one or two values. In case there are two value they are separated by a colon :, also if the first value should be empty the second (only value) would be prefixed by with a colon.

The first value can be composed of pretty any character alphanumeric and special characters, the second value 开发者_运维问答only of alphanumeric characters. Therefore a colon is not a distinct separator.

I tried some regular expression, most of them work fine for only one value, or two values without a colon in the first but if the first one is empty the regex returns the whole string as first value.

My actual code looks like:

if ($string =~ m/^(.+)(\:(\w+)|)$/){  
    $value1 = $1 || '';    
    if ($3){$value2 = $3}
}

This one works for empty string, only first value, two values without colon in first value.

Edit:

String could be:

  • Hello World! (only one value: value1='Hello World!')
  • This is a test:123 (two values: value1='This is a test' value2='123')
  • :Banana (only one value: value2='Banana')
  • T3-76: (only one value: value1='T3-76:')
  • Book:Title:Mysql (two values: value1='Book:Title' value2='Mysql')

The main problem is how to make a difference between a one value string which includes a colon and some text after the colon and a two values string with no colon in the first value. I should probably assume that if this case happen it is a two value string.

Edit2

If it makes it easier the code could be modified to not match an empty string.

Anyone got an idea?


Maybe use split with a negative lookahead assertion:

my ($a, $b) = split(/:(?!.*:)/, $string);

Note that empty values may either be undef or the empty string.


If I understand correctly, then the interpretation is ambiguous. Consider "1:2". This could be interpreted as first value being 1, second value being 2. However, since the first value can contain special characters (such as ':'), this might also be interpreted as just the first value being "1:2".

How do you expect your "interpreter" to work in this case?

EDIT:

Have you thought about using split? It will return an array.

If array is empty => string was empty.

If array is size one => first element in array is value1

If array has multiple elements => last element in array is value2, and all other elements before that concatenated is value1.

Does that help?


Try this:

^((?:(?!:[\w]*$).)*)(?::([\w]+)?)?$


I would consider doing it with an if rather than as one regex doing everything. Maybe something like:

if ( m/^(.*):([^:]*)$/ ) { $value1 = $1; $value2 = $2; }
else { $value1 = $_; $value2 = ''; }

Is it important that value-2 is only alphanumeric, or is the weaker (anything not-a-colon) test OK?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜