Regular expressions doesn't change any text in PHP - php

I have this code to replace every number (and point) and replace it by <b>and the text</b>
<?
function reem2($cadena) {
$buscarRegex = array('/^([0-9]{1}|[.])$/i');
$reemplazo = array('<b>$i</b>');
$mag = preg_replace($buscarRegex, $reemplazo, $cadena);
return $cadena;
}
$string = "1. Krewella - Can't Control Myself
2. Kdrew - Circles
3. Korn Feat. Skrillex & Kill The Noise - Narcissistic Cannibal
4. Netsky - Love Has Gone
5. Example - Midnight Run (Flux Pavilion Remix)
6. Madeon - Finale (Radio Version)
7. Feed Me Vs. Knife Party Vs. Skrillex - My Pink Reptile Party (Maluu's Slice'n'diced Mashup)
8. Krewella & Pegboard Nerds - This Is Not The End
9. Skrillex - Bangarang
10. The Prototypes - Suffocate
11. Ayah Marar - Mind Controller (Cutline Remix)
12. Skrillex Feat. Krewella - Breathe (Vocal Edit)
13. Utah Saints Vs. Drumsound & Bassline Smith - What Can You Do For Me (Tantrum Desire Remix)
14. Nero - Promises (Skrillex & Nero Remix)
15. 20 Florence & The Machine - Cosmic Love (Seven Lions Remix)";
echo reem2(nl2br($string));
?>
But it doesn't work, It doesn't change anything:
The output in HTML would be:
1. Krewella - Can't Control Myself
2. Kdrew - Circles
3. Korn Feat. Skrillex & Kill The Noise - Narcissistic Cannibal
4. Netsky - Love Has Gone
5. Example - Midnight Run (Flux Pavilion Remix)
6. Madeon - Finale (Radio Version)
7. Feed Me Vs. Knife Party Vs. Skrillex - My Pink Reptile Party (Maluu's Slice'n'diced Mashup)
8. Krewella & Pegboard Nerds - This Is Not The End
9. Skrillex - Bangarang
10. The Prototypes - Suffocate
11. Ayah Marar - Mind Controller (Cutline Remix)
12. Skrillex Feat. Krewella - Breathe (Vocal Edit)
13. Utah Saints Vs. Drumsound & Bassline Smith - What Can You Do For Me (Tantrum Desire Remix)
14. Nero - Promises (Skrillex & Nero Remix)
15. 20 Florence & The Machine - Cosmic Love (Seven Lions Remix)
What can I do?

Your regex is broken:
/^([0-9]{1}|[.])$/i
^-- start of line
^--- end of line
you are allowing only for one SINGLE character on a line by itself, so the regex can never match anything.
You probably want something more like this:
/^([\d]+)\./
which will match any number of digits at the start of the line, which are followed by a single ..

You may use the following code:
function reem2($cadena) {
$buscarRegex = array('/^(\d+\.)/mi'); // This means match any digit(s) followed by a dot at the beginning of each line. Note the m modifier
$reemplazo = array('<b>$1</b>'); // replace should be with group 1, not some vague $i
$mag = preg_replace($buscarRegex, $reemplazo, $cadena);
return $mag; // return value: fixed
}

return $cadena;
is your problem, Your doing the replace and then throwing the result away and returning the input
return $mag;
is probably what you meant
in fact your regex is also wrong
function reem2($cadena) {
$buscarRegex = array('/^([0-9]{1,2}\.)(.*)$/m');
$reemplazo = array('<b>\1</b>\2');
$mag = preg_replace($buscarRegex, $reemplazo, $cadena);
return $mag;
}
seems to be what you want.

So from what I see, your regex is incorrect and you're returning the incorrect variable in function reem2, so try replacing your function with something like this
function reem2($cadena) {
return preg_replace("/([0-9]+\.)/", "<b>$1</b>", $cadena);
}

function reem2($cadena) {
$buscarRegex = array('/^([0-9]+\.)/m'); // changed modifier to multiline
$reemplazo = array('<b>$1</b>'); // changed replacement to a capture offset
return preg_replace($buscarRegex, $reemplazo, $cadena);
}

Related

php remove duplicates from string, if duplicate length is > 4

I want to remove duplicates, if these duplicates got a length of more then 4 characters.
How can we achieve that? My current code also remove the duplicate - values.
CODE:
$seoproducttitle = 'HP Chromebook Chromebook 11 G5 EE - 11.6 inch - Intel® Celeron® - 4LT18EA#ABH';
$productnamestring = $seoproducttitle;
$findseo = array('/\h+inch (?:(i[357])-\w+|\h+\w+)?/', '/(\w+)#\w+/');
$replaceseo = array('" $1', '$1');
$productnamingseo = preg_replace($findseo, $replaceseo, $productnamestring);
echo implode(' ', array_unique(explode(' ', $productnamingseo)));
This outputs: HP Chromebook 11 G5 EE - 11.6" Intel® Celeron® 4LT18EA
It should output: HP Chromebook 11 G5 EE - 11.6" - Intel® Celeron® - 4LT18EA
Or: Apple MacBook Air MacBook Air - 13.3 inch - Intel Core i5-8e - MRE82N/A
Should be: Apple MacBook Air - 13.3 inch - Intel Core i5-8e - MRE82N/A
EXAMPLE: http://sandbox.onlinephpfunctions.com/code/5bcaaf47ca97d6dee359802f2d71c2d889c0d091
Update
Based on comments from OP, the required regex is
/(^| )(.{4,}) (.*)\2/
This looks for a group of 4 or more characters preceded by either a space or the start of the line and followed by a space, some number of other characters and then the group repeated again. The regex is replaced by $1$2 $3 which effectively removes the duplicate string. A couple of examples:
$seoproducttitle = 'Apple MacBook Air MacBook Air - 13.3 inch - Intel Core i5-8e - MRE82N/A';
echo preg_replace('/(^| )(.{4,}) (.*)\2/', "$1$2 $3", $seoproducttitle) . "\n";
$seoproducttitle = 'HP Chromebook 11 G5 EE Chromebook - 11.6 inch - Intel® Intel® Celeron® - 4LT18EA#ABH 4LT18EA#ABH';
echo preg_replace('/(^| )(.{4,}) (.*)\2/', "$1$2 $3", $seoproducttitle) . "\n";
Output:
Apple MacBook Air - 13.3 inch - Intel Core i5-8e - MRE82N/A Array
HP Chromebook 11 G5 EE - 11.6 inch - Intel® Celeron® - 4LT18EA#ABH
Updated demo on 3v4l.org
Original Answer
You could use this regex:
\b([^ ]{4,})( |$)(.*)\1
It looks for a group of 4 or more non-blank characters, followed by a space or end-of-string, followed by some number of other characters and then the first group repeated. The regex is replaced by $1$3 which effectively removes the duplicate string. e.g.
$seoproducttitle = 'HP Chromebook 11 G5 EE Chromebook - 11.6 inch - Intel® Intel® Celeron® - 4LT18EA#ABH 4LT18EA#ABH';
echo preg_replace('/\b([^ ]{4,})( |$)(.*)\1/', "$1$3", $seoproducttitle);
Output:
HP Chromebook11 G5 EE - 11.6 inch - Intel® Celeron® - 4LT18EA#ABH
Demo on 3v4l.org
Computers only do what we tell them, so you first need to explain the process to yourself in plain language. Then translate that to code. Then if you're having trouble doing that you've at least got a proper description of the problem to post on StackOverflow .
$words = explode(' ', $productnamingseo);
// start with an empty list of words we've seen
$output = [];
// for every word
foreach($words as $word) {
// if it's longer than 4 chars and we've already seen it
if( mb_strlen($word) >= 4 && in_array($word, $output) ) {
// debug: show omitted words
// $output[] = str_repeat('X', mb_strlen($word));
// skip it
continue;
}
// otherwise, add it to the list of words we've already seen
$output[] = $word;
}
var_dump(
$productnamingseo,
implode(' ', $output)
);

php a and b players consecutive stones

I have to find a php code to solve a math problem.
This is the problem description:
Players A and B are playing a new game of stones. There are N stones
placed on the ground, forming a sequence. The stones are labeled from
1 to N. Players A and B play in turns take exactly two consecutive stones
on the ground until there are no consecutive stones on the ground.
That is, each player can take stone i and stone i+1, where 1≤i≤N−1. If
the number of stone left is odd, A wins. Otherwise, B wins. Assume
both A and B play optimally and A plays first, do you know who the
winner is?
The line has N stones and are indexed from 1 to N --> N (1 ≤
N ≤ 10 000 000)
If the number of stone left is odd, A wins. Otherwise, B wins.
This is my code. It does work, but it is not correct.
<?php
$nStones = rand(1, 10000000);
$string = ("i");
$start = rand(1, 10000000);
$length = 2;
while($nStones > 0) {
substr( $nStones , $start [, $length ]): string;
}
if ($nStones % 2 == 1) {
echo "A";
} else {
echo "B";
}
?>
I think am missing the alternant subtraction of two consecutive stones by A & B, while $nStones > 0. Furthermore, the problem description mentions an optima subtraction until there is only one stone left. Therefore I guess the stones move together to their closest stones (the gaps disappear and are replaced by the closest stones).
I've made a start here:
<?php
class GameOfStones
{
const STONE_PAIR = 'OO';
const GAP_PAIR = '__';
public $line;
public function __construct($length)
{
$this->line = str_pad('', $length, self::STONE_PAIR);
}
// Removes a pair of stones from the line at nth location.
public function remove($n)
{
if(substr($this->line, $n-1, 2) == self::STONE_PAIR)
$this->line =
substr_replace($this->line, self::GAP_PAIR , $n-1, 2);
else
throw new Exception('Invalid move.');
}
// Check if there are no further possible moves.
public function is_finished()
{
return strpos($this->line, self::STONE_PAIR) === false;
}
// Representation of line.
public function __toString()
{
return implode('.', str_split($this->line)) ."\n";
}
};
$game = new GameOfStones(6);
echo $game;
var_dump($game->is_finished());
$game->remove(5);
echo $game;
var_dump($game->is_finished());
$game->remove(2);
echo $game;
var_dump($game->is_finished());
Output:
O.O.O.O.O.O
bool(false)
O.O.O.O._._
bool(false)
O._._.O._._
bool(true)
Currently this class starts by making a line which is a string of 'O' characters.
So if the length was 5, the line would be a string like this:
OOOOO
The remove method takes an index. If that index was 1, first the line is checked at the string's 0 index (your n-1) for two consecutive O's. In other words 'are there stones to remove at a given position?'. If there are stones, we do a string replacement at that position, and swap the two Os for two _s.
The is_finished method checks the line for the first occurance of two Os. In other words if there are two consecutive stones there is still a move on the line to play.
The magic method __toString, is the string representation of a GameOfStones object. That's used as a way to visualise the state of the game.
O.O.O.O._._
The above shows four stones and two gaps (I'm not sure if the dot separators are necessary - the underscores can bleed into each other that's why I've used them).
I have added example use of the code, where (two) pairs of stones are removed from a line of six stones. After each removal we check if there is another possible move, or rather if the game has ended.
There is no player attribution currently, that's left to you.
Your last rule:
'If the number of stone left is odd, A wins. Otherwise, B wins.'
I am struggling with. See these examples:
i) Line of length 3:
OOO
O__ A (1)
End: one (odd) stone left.
ii) Line of length 4:
OOOO
OO__ A (3)
____ B (1)
End: zero (even) stones left.
ii) Line of length 7:
OOOOOOO
O__OOOO A(1)
O__O__O B(5)
End: three (odd) stones left.
I'd say that the person that removes the pair so the next player can't go is the winner. In game ii) above if A had played at position 1 (O__O), then they would prevent B from playing.

how to check that a number is a mobile number of a user in pakistan and not a landline number

What i have done is remove the +92 or 0092 from the start and used the following code to check if it is a valid mobile number for a pakistani person
if(preg_match('/3[0-4][0-9](?:.*)/', $number) == 1) {
//Pakistani mobile number
} else {
// not a pakistani mobile number
}
is this approach right?
Based on the description found on wikipedia: Telephone_numbers_in_Pakistan,
then something like this pattern:
^0?3(?:[0-46]\d|55)\d{7}$
Or without considering the special case of operator 5 (SCO):
^0?3[0-6]\d{8}$
Or with including the country prefix as an optional group:
^((?:00|\+)92)?(0?3(?:[0-46]\d|55)\d{7})$
Php Test Snippet:
<?php
$telnumber='03441234567';
if(preg_match('/^((?:00|\+)92)?(0?3(?:[0-46]\d|55)\d{7})$/', $telnumber))
{
echo "matches pattern";
} else
{
echo "doesn't match pattern";
}
(^\+92[0-9]{10}$)|(^\0092[0-9]{10}$)
Here string append +92 initially then check next 10 digit or if there is 0092 in front of number then it consists of 10 digit number.
The +92 and 0092 check your ISD code initially not other.
For only accept \d{4} and 9 digit ^((0)(3))([0-9]{9})$
Pakistan mobile number examples:
+923331234567
00923331234567
03331234567
try this regex:
"^((?:00|\\+)92)?(0?3(?:[0-4])\\d{7})\$"
((?:00|\\+)92)? -> 0092 or +92 or none
0?3 -> 03 or 3
(?:[0-4]) -> after above string only 0,1,2,3,4 can be accepted (e.g. 031, 032, 033, 034)
\\d{7} -> length 7 characters will be accepted after above string
Note: other country regex can be made from these examples easily
Use the following python code to validate Pakistani Phone Number. It checks country code (+92, 0092, 92, 0) followed by a 3 and then for carrier code of 2 digits with limit of first digit (0 - 4) and limit of second digit (0 - 9) and at the end 7 digits in range (0 - 9).
import re
def validate_not_mobile(value):
pat = re.compile(r'(^((\+92)?(0092)?(92)?(0)?)(3)([0-4]{1})([0-9]{1})([0-9]{7})$)')
if re.fullmatch(pat, value):
print(f"'{value}' is a valid number!")
else:
print(f"'{value}' is NOT a valid number!")
I have tested the code with several test numbers and it has worked fine. If there is any further update I'll update it here.

how to check this special strings

I have a special strings to check with a PHP script. This is the format :
XX - XX:XX:XX - Somethings
such as :
each XX must be ?? or a pair of digit;
first XX can take every kind of digit;
second XX must be from 00 and 10;
third and fourth XX must be from 00 to 59;
somethings can be everything, it doesnt matter;
These are some example :
00 - ??:??:?? - Blablabla // OK
99 - ??:99:?? - Blablabla // NO (99 is too high)
99 - 12:50:40 - Blablabla // NO (12 is too high)
?? - AA:50:40 - Blablabla // NO (AA is not a pair of digit)
99 - 2:50:40 - Blablabla // NO (2 is not a pair of digit; I need 02)
99 -08:49:40 - Blablabla // NO (-08 need a space)
How can I do it? I think the best way is Regex, but I really don't know how to do it :) Any help is appreciated
You can do it like this
$subj = '00 - 04:38:27 - Hi';
preg_match('/^(\?\?|\d\d) - (\?\?|10|0\d):(\?\?|[0-5]\d):(\?\?|[0-5]\d) - (.*)/', $subj, $matches);
Then you can access the fields in matches:
$matches[1] = 00
$matches[2] = 04
$matches[3] = 38
$matches[4] = 27
$matches[5] = Hi
This seems to do the job (tested at http://www.spaweditor.com/scripts/regex/index.php)
/([0-9\?]{2} - (0[0-9]|10|\?\?):([0-5][0-9]|\?\?):([0-5][0-9]|\?\?) - .*)/

Bitwise operation error?

I'm developping a site for fun and I'm trying to implement a directory access control based on bitwise operators.
I've defined GUEST = 1, GROUP1 = 15 and GROUP2 = 23
If I compare
echo (23 & 1); // print 1
but if I define GUEST, GROUP1 and GROUP2:
define('GUEST', 1);
define('GROUP1', 15);
define('GROUP2', 23);
// and then
echo (GROUP2 & GUEST); // print 0
echo USER_GUEST.','.USER_ROLES1.','.USER_ROLES2; // print 1,15,23`
With GROUP1 no problem:
echo (GROUP1 & GUEST); print 1.
Where do I'm wrong ? some suggestion ?
Thanks.
I've discovered something really strange: my GUEST, GROUP1 and GROUP2 are declared inside an ini file which I parse by a function parse_ini_file(self::$fileName, true); within a class .
After I've parsed the file I define recursively the couples key=value defined under section [DEFINE] (a simply trick).
If I comment there my GROUP2=23 definition and I declare it inside the current script (GROUP2 & GUEST) return 1!
Make sure you use base 2 numbers for your groups, i.e. 1,2,34,8,16,32.... or you can step on each other. Here's the correct way to do permissions in a bitfield.
define('GUEST', 1);
define('GROUP1', 2);
define('GROUP2', 4);
$groups |= GUEST;
$groups |= GROUP1;
if($groups & GUEST) {
// This user is a guest (it is)
}
if($groups & GROUP1) {
// This user is in group 1 (it is)
}
if($groups & GROUP2) {
// This user is in group 2 (it is NOT)
}
PHP 5.3:
php > define('GUEST', 1);
php > define('GROUP1', 15);
php > define('GROUP2', 23);
php > echo GROUP2 & GUEST;
1
php > echo GROUP1 & GUEST;
1
What PHP version are you using?
Artefacto pointed out a possible string issue (e: but appears to have retracted his post, hm). Again in 5.3:
php > var_export(GUEST);
1
php > var_export(GROUP1);
15
php > var_export(GROUP2);
23
php > define('GUEST_AS_STRING', '1');
php > var_export(GUEST_AS_STRING);
'1'
php > echo GROUP1 & GUEST_AS_STRING;
1
php > echo GROUP2 & GUEST_AS_STRING;
1
'1' is character 49. 49 & 15 is 1, but 49 & 23 is 17. I'm not convinced that this is a string issue...
Solved.
I completely misunderstood a declaration in php manual where in Changelog they say:
5.2.4 Keys and section names consisting of numbers are now evaluated as PHP integers thus numbers starting by 0 are evaluated as octals and numbers starting by 0x are evaluated as hexadecimals.
It's absolutly clear: keys and section name ... not values!
The parse_ini_file() function evaluates integers values as PHP string even if they aren't enclosed in double quotes. This is pity, but so it is ;-)
Thanks for your collaboration

Categories