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?
精彩评论