help me to improve my existing regex code - regex

I'm using this /\{\$?([^# ]+)\#?([^ ]+)? ?([^|]+)?[ \|]?([^\}]+)?\}/ perl-compatible regular expressionFor matching strings like :
{$string#asdf#asdf can you hear me? |ucfirst|strtoupper}
Outputting this :
Array
(
[0] => {$string#asdf#asdf can you hear me? |ucfirst|strtoupper}
[1] => string
[2] => asdf#asdf
[3] => can you hear me?
[4] => ucfirst|strtoupper
)
if used with PHP's preg_replace_callback function,
but with string like {$string#asdf#asdf can you hear me? ucfirst|strtoupper} it's outputting this :
Array
(
[0] => {$string#asdf#asdf can you hear me? ucfirst|strtoupper}
[1] => string
[2] => asdf#asdf
[3] => can you hear me? ucfirst
[4] => strtoupper
)
can you improve it the way you wish so that it will be able to match string like :
{$string#asdf#asdf can you hear me? ucfirst|strtoupper} (notice: "|" removed in front of ucfirst) without affecting the result of the array.(ie output should be the same as the first printed array above)

This Regex string already matches both of the samples you provided. What are you really asking here?

Not clear exactly what you're wanting, but here's my best guess based on what you specified:
{\$([^#]*)#(\S*) (.*?) (\S*)}
That will give the following for matches 1-4
Everything up to the first # sign
Everything after the first # sign and before the next space
Everything else between #2 and #4
The last string of characters not containing a space
In the example
{$string#asdf#asdf can you hear me? ucfirst|strtoupper}
We have:
string
asdf#asdf
can you hear me?
ucfirst|strtoupper

Related

mvc phone number regex "or"

Im trying to make validation for phone number or cellphone number with country prefix (or without)
for ex:
1. 55-123-1234(home num) or 055-123-1234(cell phone) => [2,3][3][4]
2. or +999-55-123-1234 => +[3][2][3][4]
For now Im using the following regex: [RegularExpression(#"^([0-9]{2,3})[-. ]?[0-9]{3}[-. ]?([0-9]{4,6})$" but it covers only 1.
the last [3][4] will always be so my question is if there is a way to write => ([2,3]) or (+[3] [2])
The validation needs to cover (+[3] [2]) [3] [4] or ([2,3]) [3] [4] make it valid
If there is any way to do add "or" between (+[3][2]) to ([2,3])?
or maybe there is other way to it to make it valid?
Thanks in advance
OR in regex is done with the | character.
+[3][2] or [2,3] is then written : \+\d{3}\-\d{2}|\d{2,3}
So for your complete regex, you can try the following :
(?:\+\d{3}[-. ]?\d{2}|\d{2,3})[-. ]?\d{3}[-. ]?\d{4}
Demo here

Using Regular expression to search for a value but exlude that string from the results?

This is prob really simple, I'm new to regular expressions but say I wanted to find the 2 numbers preceding some characters. i.e "12 qty"
So I'm using \d\d.qty to bring back the match "12 qty" but I want to exclude the word qty?
I have tried using \d\d.qty*([^qty]*) but it doesn't work.
You need to use a positive look ahead, depends on which language of course:
(\d\d)(?=\sqty)
You could use (\d\d)(.qty) so you get back
Array
(
[0] => Array
(
[0] => 12 qty
)
[1] => Array
(
[0] => 12
)
[2] => Array
(
[0] => qty
)
)
Now use second item of the array and you have, what you want

Parse labeled param strings with Regex

Can anyone help me with this one?
My objective here is to grab some info from a text file, present the user with it and ask for values to replace that info so to generate a new output. So I thought of using regular expressions.
My variables would be of the format: {#<num>[|<value>]}.
Here are some examples:
{#1}<br>
{#2|label}<br>
{#3|label|help}<br>
{#4|label|help|something else}<br><br>
So after some research and experimenting, I came up with this expression: \{\#(\d{1,})(?:\|{1}(.+))*\}
which works pretty well on most of the ocasions, except when on something like this:
{#1} some text {#2|label} some more text {#3|label|help}
In this case variables 2 & 3 are matched on a single occurrence rather than on 2 separate matches...
I've already tried to use lookahead commands for the trailing } of the expression, but I didn't manage to get it.
I'm targeting this expression for using into C#, should that further help anyone...
I like the results from this one:
\{\#(\d+)(?:|\|(.+?))\}
This returns 3 groups. The second group is the number (1, 2, 3) and the third group is the arguments ('label', 'label|help').
I prefer to remove the * in favor of | in order to capture all the arguments after the first pipe in the last grouping.
A regular expression which can be used would be something like
\{\#(\d+)(?:\|([^|}]+))*\}
This will prevent reading over any closing }.
Another possible solution (with slightly different behaviour) would be to use a non-greedy matcher (.+?) instead of the greedy version (.+).
Note: I also removed the {1} and replaced {1,} with + which are equivalent in your case.
Try this:
\{\#(\d+)(?:\|[^|}]+)*\}
In C#:
MatchCollection matches = Regex.Matches(mystring,
#"\{\#(\d+)(?:\|[^|}]+)*\}");
It prevents the label and help from eating the | or }.
match[0].Value => {#1}
match[0].Groups[0].Value => {#1}
match[0].Groups[1].Value => 1
match[1].Value => {#2|label}
match[1].Groups[0].Value => {#2|label}
match[1].Groups[1].Value => 2
match[2].Value => {#3|label|help}
match[2].Groups[0].Value => {#3|label|help}
match[2].Groups[1].Value => 3

simplify my multiline regex - match plus next x amount of lines

I have the following Haml code:
%ul#sub-nav
%li.li1
%a{:href => "/dsadasd/"} dasdasd
%li.li2
%a.selected{:href => "/asdadasd"} Tasdada /asdas
%li.li3
%a{:href => "/dasd/"} asdasd
%li.li4
%a{:href => "/wdasn/"} das
I seem to be able to match this with the following repetitive regex - %ul#sub-nav\n.*\n^.*\n^.*\n^.*\n^.*\n^.*\n^.*\n^.* in intellij's rubymine ide.
This looks way too repetitive. Help appreciated.
If you want to match %ul#sub-nav plus the eight following lines, this should do:
%ul#sub-nav(\n.*$){8}

Regex Help, How do I make order of expressions not matter?

I can't figure out how to get the order of the incoming string parameters (price,merchant,category) will not matter to the regex. My regex matches the parts of the string but not the string as a whole. I need to be able to add \A \Z to it.
Pattern:
(,?price:(;?(((\d+(\.\d+)?)|min)-((\d+(\.\d+)?)|max))|\d+)+){0,1}(,?merchant:\d+){0,1}(,?category:\d+){0,1}
Sample Strings:
price:1.00-max;3-12;23.34-12.19,category:3
merchant:25,price:1.00-max;3-12;23.34-12.19,category:3
price:1.00-max;3-12;23.34-12.19,category:3,merchant:25
category:3,price:1.00-max;3-12;23.34-12.19,merchant:25
Note: I'm going to add ?: to all my groups after I get it working.
You should probably just parse this string through normal parsing. Split it at the commas, then split each of those pieces into two by the colons. You can store validation regexes if you'd like to check each of those inputs individually.
If you do it through regex, you'll probably have to end up saying "this combination OR this combination OR this combination", which will hurt real bad.
You have three options:
You can enumerate all the possible orders. For 3 variables there are 6 possibilities. Obviously this doesn't scale;
You can accept possible duplicates; or
You can break the string up and then parse it.
(2) means something like:
/(\b(price|category|merchant)=(...).*?)*/
The real problem you're facing here is that you're trying to parse what is essentially a non-regular language with a regular expression. A regular expression describes a DFSM (deterministic finite state machine) or DFA (deterministic finite automaton). Regular languages have no concept of state so the expression can't "remember" what else there has been.
To get to that you have to add a "memory" usually in the form of a stack, which yields a PDA (pushdown automaton).
It's exactly the same problem people face when they try and parse HTML with regexes and get stuck on tag nesting issues and similar.
Basically you accept some edge conditions (like repeated values), split the string by comma and then parse or you're just using the wrong tool for the job.
How about don't try and do it all with one Cthulhugex?
/price:([^,]*)/
/merchant:([^,]*)/
/category:([^,]*)/
$string=<<<EOF
price:1.00-max;3-12;23.34-12.19,category:3
merchant:25,price:1.00-max;3-12;23.34-12.19,category:3
price:1.00-max;3-12;23.34-12.19,category:3,merchant:25
category:3,price:1.00-max;3-12;23.34-12.19,merchant:25
EOF;
$s = preg_replace("/\n+/",",",$string);
$s = explode(",",$s);
print_r($s);
output
$ php test.php
Array
(
[0] => price:1.00-max;3-12;23.34-12.19
[1] => category:3
[2] => merchant:25
[3] => price:1.00-max;3-12;23.34-12.19
[4] => category:3
[5] => price:1.00-max;3-12;23.34-12.19
[6] => category:3
[7] => merchant:25
[8] => category:3
[9] => price:1.00-max;3-12;23.34-12.19
[10] => merchant:25
)