How to obtain multiple custom placeholder content? - php

In PHP I have a string that can contain any quantity of customer placeholders. In this case I am using '[%' & '%]' as the custom placeholders for each iteration.
If my string is equal to:
"test [%variable1%] test test [%variable2%]"
How do I extract the 'variables' so I will have something like this:
array(
[0] => variable1,
[1] => variable2
);
At the moment I have: \b[\[%][a-z.*][\]%]\b but I know this is incorrect.

Use preg_match_all function to do a global match.
$re = "~(?<=\[%).*?(?=%])~m";
$str = "test [%variable1%] test test [%variable2%]";
preg_match_all($re, $str, $matches);
print_r($matches[0]);
(?<=\[%) positive lookbehind which asserts that the match must be preceeded by [% symbols. (?=%]) asserts that the match must be followed by %] symbols. .*? will do a non-greedy match of any character zero or more times.
Output:
Array
(
[0] => variable1
[1] => variable2
)
DEMO

$re = "/\\[%(.*?)%\\]/";
$str = "test [%variable1%] test test [%variable2%]";
preg_match_all($re, $str, $matches);
Regex used:
/\[%(.*?)%\]/g

Related

Extract uppercase words from a string

Edit i resolve my problem.
This is the solution
$string = "Hello my Name is Paloppa. Im' 20 And? Hello! Words I Io Man";
// Word boundary before the first uppercase letter, followed by any alphanumeric character
preg_match_all( '/(?<!^)\b[A-Z][a-z]{1,}\b(?!["!?.\\\'])/', $string, $matches);
print_r( $matches[0] );
Now i have one more question
Every time it founds a word, the word is inserted in a position of the array.
If i have this phrase "Whats is your Name and Surname? My Name And Surname' is Paolo Celio and Serie A Iim 25 Thanksbro Bro Ciao"
this is my code
$string = "Whats is your Name and Surname? My Name And Surname' is Paolo Celio and Serie A Iim 25 Thanksbro Bro Ciao";
// Word boundary before the first uppercase letter, followed by any alphanumeric character
preg_match_all( '/(?<!^)\b([A-Z][a-z]+ +){1,}\b(?!["!?.\\\'])/', $string, $matches);
print_r( $matches[0] );
the output is the following
Array (
[0] => Name
[1] => Name And Surname
[2] => Paolo Celio
[3] => Serie
[4] => Iim
[5] => Thanksbro Bro
)
Why it doesn't join Serie A instead it didn't print A?
Why the last word doesn't in the output?
Thanks
EDIT
I resolve my problem, this is my REGEX
preg_match_all('/(?<!^)\b[A-Z]([a-z0-9A-Z]| [A-Z]){1,}\b(?!["!?.\\\'])/', $string, $matches);
You can use..
<?php
$test="the Quick brown Fox jumps Over the Lazy Dog";
preg_match_all("/[A-Z][a-z]*/",$test,$op);
$output = implode(' ',$op[0]);
echo $output;
?>
This is slightly complicated, when it comes to edge cases, yet we would simply define two char classes based on our desired outputs and inputs, maybe with a word boundary, with an expression similar to:
(?=[^I'])\b([A-Z][a-z'é]+)\b
and we would expand it based on our cases.
Demo
Test
$re = '/(?=[^I\'])\b([A-Z][a-z\'é]+)\b/m';
$str = 'Hello my name is Paloppa. I\'m 20 And i love Football.
Hello my name is Chloé. I\'m 20 And i love Football.
Hello my name is Renée O\'neal. I\'m 20 And i love Football.';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
var_dump($matches);
RegEx Circuit
jex.im visualizes regular expressions:
To extract full words you'll need to use word boundaries and character classes to match the remaining part of the word, and use lookbehinds to exclude previous content:
$string = "Hello my Name is Paloppa. I'm 20 And? Hello! Words' Man";
// Word boundary before the first uppercase letter, followed by any alphanumeric character
preg_match_all( '/(?<!^)(?<!\. )\b[A-Z][a-zA-Z]*\b(?!["!?\\\'])/', $string, $matches);
print_r( $matches[0] );
If you want Capitalized words only, excluding MixedCase words, replace [a-zA-Z] with just [a-z].
Demo here
You can fastest way use.
$test="Hi There this Is my First Job";
preg_match_all('/[A-Z][a-z]*/', $test, $matches, PREG_OFFSET_CAPTURE);
$res=array();
foreach( $matches[0] as $key=> $value){
$res[]=$value[0];
}
print_r($res);
OUTPUT:
Array
(
[0] => Hi
[1] => There
[2] => Is
[3] => First
[4] => Job
)
DEMO

regex: select all characters before and after a specific string

I want to select all text before and after a specific substring, I used the following expression to do that, but it not selecting all the needed text:
/^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)*/
for example:
$re = '/^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)*/';
$str = 'customFields[<?php echo $field["id"]; ?>][type]';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
it will select only this part customFields[, while the expected result should be customFields[ and ][type]
check this link for debugging
The pattern ^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)* uses a tempered greedy token which matches any character except a newline from the start of the string ^ that fulfills the assertion of the negative lookahead.
That will only match customFields[
For your example data you could make use of a tempered greedy token regex demo, but instead you could also just make use of a negated character class and SKIP FAIL:
^[^[]+\[|<\?php echo\s(.*?)\;\s\?\>(*SKIP)(*FAIL)|\]\[[^]]*\]
Regex demo | Php demo
For example
$re = '/^[^[]+\[|<\?php echo\s(.*?)\;\s\?\>(*SKIP)(*FAIL)|\]\[[^]]*\]/';
$str = 'customFields[<?php echo $field["id"]; ?>][type]';
preg_match_all($re, $str, $matches, PREG_SET_ORDER);
print_r($matches);
Result
Array
(
[0] => Array
(
[0] => customFields[
)
[1] => Array
(
[0] => ][type]
)
)
To get a more exact match you might also use capturing groups:
^((?:(?!<\?php echo[\s?](?:.*?)\;\s\?>).)*)<\?php echo\s(?:.*?)\;[\s?]\?>(.*)$
regex demo | Php demo
What about using positive lookarounds:
(.*)(?=\<\?php echo)|(?<=\?\>)(.*)
Demo

Words finder regex fails

I'm using this pattern to check if certain words exists in a string:
/\b(apple|ball|cat)\b/i
It works on this string cat ball apple
but not on no spaces catball smallapple
How can the pattern be modified so that the words match even if they are combined with other words and even if there are no spaces?
Remove \b from the regex. \b will match a word boundary, and you want to match the string that is not a complete word.
You can also remove the capturing group (denoted by ()) as it is not required any longer.
Use
/apple|ball|cat/i
Regex Demo
An IDEONE PHP demo:
$re = "/apple|ball|cat/i";
$str = "no spaces catball smallapple";
preg_match_all($re, $str, $matches);
print_r($matches[0]);
Results:
[0] => cat
[1] => ball
[2] => apple

regex getting number from tags

I am trying get this number which is between tags << >>
333333
from
string = "my subject <<my-support-id=333333>>"
Can you give any advise as I am not getting anywhere
I am trying to get this using preg_match function in php.
How about the regex
/<<[^\d]+(\d+)>>/
[^\d]+ Negated character class. would match anything other than digits, \d
(\d+) Capture group 1 will contain the digits within the << >>
Regex Demo
Test
preg_match("/<<[^\d]+(\d+)>>/", "my subject <<my-support-id=333333>>",$matches);
print_r($matches[1]);
=> 333333
OR
/<<[^=]+=(\d+)>>/
Test
preg_match ( "/<<[^=]+=(\d+)>>/", "my subject <<my-support-id=333333>>",$matches);
print_r($matches[1]);
=> 333333
Try this:
preg_match_all('/\=([0-9]+)>/','my subject <<my-support-id=333333>>', $out, PREG_PATTERN_ORDER);
echo $out[1][0];
You could do this -
$string = "my subject <<my-support-id=333333>>";
$pattern = '/\d+/';
preg_match($pattern, $string, $matches);
print_r($matches);
And the output would be Array ( [0] => 333333 )
EXAMPLE

Get all occurrences of words between curly brackets

I have a text like:
This is a {demo} phrase made for {test}
I need to get
demo
test
Note: My text can have more than one block of {}, not always two. Example:
This is a {demo} phrase made for {test} written in {English}
I used this expression /{([^}]*)}/ with preg_match but it returns only the first word, not all words inside the text.
Use preg_match_all instead:
preg_match_all($pattern, $input, $matches);
It's much the same as preg_match, with the following stipulations:
Searches subject for all matches to the regular expression given in
pattern and puts them in matches in the order specified by flags.
After the first match is found, the subsequent searches are continued
on from end of the last match.
Your expression is correct, but you should be using preg_match_all() instead to retrieve all matches. Here's a working example of what that would look like:
$s = 'This is a {demo} phrase made for {test}';
if (preg_match_all('/{([^}]*)}/', $s, $matches)) {
echo join("\n", $matches[1]);
}
To also capture the positions of each match, you can pass PREG_OFFSET_CAPTURE as the fourth parameter to preg_match_all. To use that, you can use the following example:
if (preg_match_all('/{([^}]*)}/', $s, $matches, PREG_OFFSET_CAPTURE)) {
foreach ($matches[1] as $match) {
echo "{$match[0]} occurs at position {$match[1]}\n";
}
}
As the { and } are part of regex matching syntax, you need to escape these characters:
<?php
$text = <<<EOD
this {is} some text {from}
which I {may} want to {extract}
some words {between} brackets.
EOD;
preg_match_all("!\{(\w+)\}!", $text, $matches);
print_r($matches);
?>
produces
Array
(
[0] => Array
(
[0] => {is}
[1] => {from}
[2] => {may}
[3] => {extract}
[4] => {between}
)
... etc ...
)
This example may be helpful to understand the use of curly brackets in regexes:
<?php
$str = 'abc212def3456gh34ij';
preg_match_all("!\d{3,}!", $str, $matches);
print_r($matches);
?>
which returns:
Array
(
[0] => Array
(
[0] => 212
[1] => 3456
)
)
Note that '34' is excluded from the results because the \d{3,} requires a match of at least 3 consecutive digits.
Matching portions between pair of braces using RegEx, is less better than using Stack for this purpose. Using RegEx would be something like «quick and dirty patch», but for parsing and processing input string you have to use a stack. Visit here for the concept and here for applying the same.

Categories