PHP - Convert ereg to preg_match - php

I have a script I have used for quite a while that validates UK postcodes, issue I have is one part of the function uses ereg rather than preg_match.
Could someone point me in the right direction with the below please? I have added delimiters but not getting the same results as I was before.
$alpha1 = "[abcdefghijklmnoprstuwyz]";
$alpha2 = "[abcdefghklmnopqrstuvwxy]";
$alpha3 = "[abcdefghjkstuw]";
$alpha4 = "[abehmnprvwxy]";
$alpha5 = "[abdefghjlnpqrstuwxyz]";
// Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA
$pcexp[0] = '/^(' . $alpha1 . '{1}' . $alpha2 . '{0,1}[0-9]{1,2})([0-9]{1}' . $alpha5 . '{2})$/';
// Expression for postcodes: ANA NAA
$pcexp[1] = '/^(' . $alpha1 . '{1}[0-9]{1}' . $alpha3 . '{1})([0-9]{1}' . $alpha5 . '{2})$/';
// Expression for postcodes: AANA NAA
$pcexp[2] = '/^(' . $alpha1 . '{1}' . $alpha2 . '[0-9]{1}' . $alpha4 . ')([0-9]{1}' . $alpha5 . '{2})$/';
// Exception for the special postcode GIR 0AA
$pcexp[3] = '/^(gir)(0aa)$/';
// Standard BFPO numbers
$pcexp[4] = '/^(bfpo)([0-9]{1,4})$/';
// c/o BFPO numbers
$pcexp[5] = '/^(bfpo)(c\/o[0-9]{1,3})$/';

At a first glance, everything looks OK, but you need to make the regex case-insensitive by adding an i after the closing delimiter:
$pcexp[4] = '/^(bfpo)([0-9]{1,4})$/i';
and so on.
Your regexes don't allow for spaces between the parts of the postcode. Is this intentional? If not, add a \s* everywhere spaces are legal
Also, you can drop all instances of {1} and replace each {0,1} with ?.

Related

RegEx (preg_match_all in PHP) to capture series of <tags containing numbers> up to the first alphanumeric character

The problem here is the conflict between numbers and alphanumeric in the problem description.
Given the text:
<0><1><2><3><4><5><6><7><8><9><10><11><12><13><14><15><16><17><18>The
next 11 keys can change the SWING from OFF (50%) to
<19><20><21><22><23><24><25>80<26><27><28><29><30><31><32>% during
arpeggiator or sequencer operation.<33><34>
I need to extract the following four groups:
<0><1><2><3><4><5><6><7><8><9><10><11><12><13><14><15><16><17><18>
<19><20><21><22><23><24><25>
<26><27><28><29><30><31><32>
<33><34>
Reason: we want to display this in a much more user-friendly way as...
[1]The next 11 keys can change the SWING from OFF (50%) to [2]80[3]%
during arpeggiator or sequencer operation.[4]
Current code:
$pattern = '<[\d<>' . REGSTART . REGEND . REGSTARTSQ . REGENDSQ . '\{\}]+>';
$numberofsupertags = preg_match_all('/(' . $pattern . ')/', $source, $superchunks);
echo '<pre>';
print_r($superchunks);
echo '</pre><br>';
(REGSTART/REGEND/REGSTARTSQ/REGENDSQ refer to other possible pairs of symbols, like 【】 or 〖〗 etc.)
gives three groups:
<0><1><2><3><4><5><6><7><8><9><10><11><12><13><14><15><16><17><18>
<19><20><21><22><23><24><25>80<26><27><28><29><30><31><32>
<33><34>
As you can see, the RegEx fails to take into account sequences of only numbers between tags.
I've tried lots of things:
$pattern = '([<|' . REGSTART . REGSTARTSQ . '|\{]\d+?[>|' . REGEND . REGENDSQ . | \}])+';
$pattern = '<[\d<>' . REGSTART . REGEND . REGSTARTSQ . REGENDSQ . '\{\}]+[>(?=\d)|>]';
...but to no avail.
What is the correct solution and where do I go wrong? This looks really simple, but apparently it isn't.
You can use
(?:<(?:{\d+}|【\d+】|〖\d+〗|\d+)>)+
See the regex demo. Details:
(?: - start of a non-capturing group:
< - a < char
(?:{\d+}|【\d+】|〖\d+〗|\d+) - one of the alternatives: { + one or more digits + }, 【 + one or more digits + 】, 〖 + one or more digits + 〗 or one or more digits
> - a > char
)+ - one or more times.
See the PHP demo:
$source = '<0><1><2><3><4><5><6><7><8><9><10><11><12><13><14><15><16><17><18>The next 11 keys can change the SWING from OFF (50%) to <19><20><21><22><23><24><25>80<26><27><28><29><30><31><32>% during arpeggiator or sequencer operation.<33><34>';
$cnt = 0;
echo preg_replace_callback('~(?:<(?:{\d+}|【\d+】|〖\d+〗|\d+)>)+~u', function($m) use (&$cnt) {
return '['. ++$cnt .']';
}, $source);
// => [1]The next 11 keys can change the SWING from OFF (50%) to [2]80[3]% during arpeggiator or sequencer operation.[4]

Match an actual dollar symbol in php regex

I haven't used regex in a long time and can't figure out how to match an actual dollar symbol and any reference to dollar symbol and regex tells me about the special meanings and cases. I need to match a $. I expected that \$ or $$ was supposed to escape it, but I'm still not matching it.
Here's my text
(WW) Capacity Charge
. . . . . . . . . . . . . . . . $ 123.45
WW Commodity Charge . . . . . . . . . $ 67.89
I'm trying to capture 123.45 I figured I should just match the first occurrence where some characters are sandwiched between the dollar symbol, space and a newline. Here are a few of the regexes I've tried.
preg_match("|(?<=\$\s)(.*)(?=\n)|",$data[1],$matches); //no matches
preg_match("|(?<=$\s)(.*)(?=\n)|",$data[1],$matches); //no matches
preg_match("|(?<=$)(.*)(?=\n)|",$data[1],$matches); //no matches
preg_match("|(?<=\$)(.*)(?=\n)|",$data[1],$matches); //no matches
preg_match("|(?<=$$)(.*)(?=\n)|",$data[1],$matches); //no matches
Just to check that something matches I even did
preg_match("|(?<=\.)(.*)(?=\n)|",$data[1],$matches); // . . . . . . . . . . . . . . . $ 123.45
preg_match("|(?<=.)(.*)(?=\n)|",$data[1],$matches); // . . . . . . . . . . . . . . . $ 123.45
preg_match("|(?<=1)(.*)(?=\n)|",$data[1],$matches); // 23.45
How can I match the text between the $ and the newline?
You are in double quotes so you need to escape twice (once for PHP, then once for PCRE). I prefer a character class though because that works in all regex flavors.
(?<=[$]\s)(.*)(?=\n)

Multiple answer with preg_replace

I have a problem with preg_replace in PHP.
My text:
[Derp] a
• [Derp] a
My regex:
$simple_search[0] = '/\[(.*?)\] (.*?)/is';
$simple_search[1] = '/\• \[(.*?)\] (.*?)/is';
My subject:
$simple_replace[0] = "[color=#009D9D][$1][/color] $2";
$simple_replace[1] = "[color=#30BA76]• [$1][/color] [color=#92CF91]$2[/color]";
After preg_replace:
[color=#009D9D][Derp][/color] a
[color=#30BA76]#color=#009D9D][Derp][/color[/color] [color=#606090]: [/color]a
(it's a tool for coloring quotes)
[Derp] a and
• [Derp] a must not have the same color.
The problem is that the first search then replaces that this is not the right thing.
How can I detect that research is equal to the string?
replace your first regexp:
/(?<!\• )\[(.*?)\] (.*?)/is
means can not have front of the "[" an "•" and a space. Also if the • stands in beginning of your lines then you could put ^ front of it
$str = '[Derp] a
• [Derp] a';
$simple_search[0] = '/(\• )?(?P<m2>\[.*?\]) (?P<m3>.*)/i';
echo $str = preg_replace_callback($simple_search[0],
function ($m) {
if (!$m[1]) return '[color=#009D9D]' . $m[2] . '[/color] ' . $m[3];
else return '[color=#30BA76]• ' . $m[2] . '[/color] [color=#92CF91]' . $m[3] . '[/color]';
}, $str
);
result
[color=#009D9D][Derp][/color] a
[color=#30BA76]• [Derp][/color] [color=#92CF91]a[/color]

PHP reg exp - where did DOI go?

I just want to replace "doi:yyyy.yyyy" here, but $1 does not give me back that text. Why? ;-)
$zp_citation['citation'] = preg_replace('(doi:[^ <]*)',
'<b>' . '$1' . " - where did doi go?" . '</b>',
$zp_citation['citation'],
1);
You are missing required regex delimiters:
$zp_citation['citation'] = preg_replace('/(doi:[^ <]*)/',
'<b>' . '$1' . " - where did doi go?" . '</b>',
$zp_citation['citation'], 1);

PHP regex split text to insert HTML

Very(!) new to regex but...
I have the following text strings outputted from a $title variable:
A. This is a title
B. This is another title
etc...
I'm after the following:
<span>A.</span> This is a title
<span>B.</span> This is another title
etc...
Currently I have the following code:
$title = $element['#title'];
if (preg_match("([A-Z][\.])", $title)) {
return '<li' . drupal_attributes($element['#attributes']) . ">Blarg</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
This replaces anything A. through to Z. with Blarg however I'm not sure how to progress this?
In the Text Wrangler app I could wrap regex in brackets and output each argument like so:
argument 1 = \1
argument 2 = \2
etc...
I know I need to add an additional regex to grab the remainder of the text string.
Perhaps a regex guru could help and novice out!
Thanks,
Steve
Try
$title = 'A. This is a title';
$title = preg_replace('/^[A-Z]\./', '<span>$0</span>', $title);
echo $title;
// <span>A.</span> This is a title
If the string contains newlines and other titles following them, add the m modifier after the ending delimiter.
If the regex doesn't match then no replacements will be made, so there is no need for the if statement.
Is it always just 2 char ("A.", "B.", "C.",...)
because then you could work with a substring instead of regex.
Just pick of the first 2 chars of the link and wrap the span around the substring
Try this (untested):
$title = $element['#title'];
if (preg_match("/([A-Z]\.)(.*)/", $title, $matches)) {
return '<li' . drupal_attributes($element['#attributes']) . "><span>{$matches[0]</span>{$matches[1]}</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
The change here was to first add / to the start and end of the string (to denote it's a regex), then remove the [ and ] around the period . because that's just a literal character on its own, then to add another grouping which will match the rest of the string. I also Added a $matches to preg_match() to place these two matches in to to use later, which we do on the next life.
Note: You could also do this instead:
$title = preg_replace('/^([A-Z]\.)/', "<span>$1</span>", $title);
This will simply replace the A-Z followed by the period at the start of the string (denoted with the ^ character) with <span>, that character (grabbed with the brackets) and </span>.
Again, that's not tested, but should give you a headstart :)

Categories