How to do such string manipulations in PHP? - php

I need to convert
"01,02,03,04,05,07:01"
to:
<b>07</b><b>09</b><b>30</b><b class="color_blue_ball">11</b>
That is ,wrap those before : with <b></b> ,but those after : with <b class="color_blue_ball"></b>.If there's no :,all should be wrapped with <b></b>
Anyone knows how to do this?

No need for regex:
echo '<b>' . str_replace(array(',', ':'), array('</b><b>', '</b><b class="color_blue_ball">'), "01,02,03,04,05,07:01") . '</b>';
Edit: if the "01,02,03,04,05,07:01,04,06" is valid, then the idea the same but explode is added:
$parts = explode(':', "01,02,03,04,05,07,01,04:06");
echo '<b>' . str_replace(',', '</b><b>', $parts[0]) . (isset($parts[1]) ? str_replace(',', '</b><b class="color_blue_ball">', ',' . $parts[1]) : '') . '</b>';

A tad more verbose:
<?php
function wrapValues($array, $wrapper) {
$result = array();
foreach ($array as $elem) {
$result []= str_replace('?', $elem, $wrapper);
}
return implode('', $result);
}
$values = "01,02,03,04,05,07:01,02";
$firstWrapper = '<b>?</b>';
$secondWrapper = '<b class="color_blue_ball">?</b>';
list($first, $second) = explode(':', $values);
echo wrapValues(explode(',', $first), $firstWrapper) .
wrapValues(explode(',', $second), $secondWrapper);

I don't know if it's the best way to do it, but I would probably split the string on the :, then on ,, and then deal with each part separately and join them back together.

Related

Unexpected result using OR operator in regular expression

I've a problem with a regular expression. I have a text which is read from a file. The text can contain one or more IDs separated by comma.
And then I have a list of IDs and want to check if one of these IDs match with my text so I try to use an OR operator:
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/' . $idString . '/', $text)) {
echo 'yes' . PHP_EOL;
} else {
echo 'no' . PHP_EOL;
}
I'm expecting that nothing matches because the IDs 1453 and 2018 are not found in my lookup string but it matches. I think that's because the ID 3 matches with 1453 but this is not correct for my use case.
That's too easy to work around it using arrays. You shouldn't use Regular Expressions if you can work with them but it seems this is not your real problem but an MCVE for a different one.
You should use word boundaries \b otherwise a number like 4 is found in 1453. preg_match() third argument holds results to analyze what is going on.
preg_match('/\b(?:' . $idString . ')\b/', $text, $match)
The syntax for preg_match is ($pattern, $text). Change it as follows, worked for me.
<?php
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/(' . $text . ')/', $idString)) {
echo 'yes' . PHP_EOL;
} else {
echo 'no' . PHP_EOL;
}
?>
You can see what gets matched by your Regex by outputting the matches, eg:
if (preg_match('/' . $idString . '/', $text, $matches)) {
echo 'yes' . PHP_EOL;
print_r($matches);
} else {
echo 'no' . PHP_EOL;
}
You'd have to adapt your regex to match against whole words only... for example like this:
if (preg_match('/\b(' . $idString . ')\b/', $text)) {
https://regex101.com/r/M1Pieb/2/
Or you could avoid using regex altogether (recommended, its getting a bit crazy..) by using explode
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idStrings = explode(',', $idString);
$values = ['1453', '2018'];
$matchedValue = null;
foreach ($values as $value) {
if (in_array($value, $idStrings)) {
$matchedValue = $value;
break;
}
}
if ($matchedValue !== null) {
echo 'yes: ' . $matchedValue;
} else {
echo 'no';
}

Is it possible to convert "x.y.z" to "x[y][z]" using regexp?

What is the most efficient pattern to replace dots in dot-separated string to an array-like string e.g x.y.z -> x[y][z]
Here is my current code, but I guess there should be a shorter method using regexp.
function convert($input)
{
if (strpos($input, '.') === false) {
return $input;
}
$input = str_replace_first('.', '[', $input);
$input = str_replace('.', '][', $input);
return $input . ']';
}
In your particular case "an array-like string" can be easily obtained using preg_replace function:
$input = "x.d.dsaf.d2.d";
print_r(preg_replace("/\.([^.]+)/", "[$1]", $input)); // "x[d][dsaf][d2][d]"
From what I can understand from your question; "x.y.z" is a String and so should "x[y][z]" be, right?
If that is the case, you may want to give the following code snippet a try:
<?php
$dotSeparatedString = "x.y.z";
$arrayLikeString = "";
//HERE IS THE REGEX YOU ASKED FOR...
$arrayLikeString = str_replace(".", "", preg_replace("#(\.[a-z0-9]*[^.])#", "[$1]", $dotSeparatedString));
var_dump($arrayLikeString); //DUMPS: 'x[y][z]'
Hope it helps you, though....
Using a fairly simple preg_replace_callback() that simply returns a different replacement for the first occurrence of . compared to the other occurrences.
$in = "x.y.z";
function cb($matches) {
static $first = true;
if (!$first)
return '][';
$first = false;
return '[';
}
$out = preg_replace_callback('/(\.)/', 'cb', $in) . ((strpos('.', $in) !== false) ? ']' : ']');
var_dump($out);
The ternary append is to handle the case of no . to replace
already answered but you could simply explode on the period delimiter then reconstruct a string.
$in = 'x.y.z';
$array = explode('.', $in);
$out = '';
foreach ($array as $key => $part){
$out .= ($key) ? '[' . $part . ']' : $part;
}
echo $out;

PHP Similar Words using soundex with array

I am creating a findSpellings function that has two parameters $word and $allWords. $allwords is an array that has mis-spellings of words that could sound similar to the $word variable. What I am trying to accomplish is to print out all words that are similar to the $word based on the soundex function. I am having trouble printing out the array with words. My function that I have is below. Any help would be greatly appreciated:
<?php
$word = 'stupid';
$allwords = array(
'stupid',
'stu and pid',
'hello',
'foobar',
'stpid',
'supid',
'stuuupid',
'sstuuupiiid',
);
function findSpellings($word, $allWords){
while(list($id, $str) = each($allwords)){
$soundex_code = soundex($str);
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
else {
return false;
}
}
}
print_r(findSpellings($word, $allWords));
?>
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
return $word;
return $allwords;
}
You can't have 2 returns, the first return will exit the code.
You could just do something like this:
if (soundex($word) == $soundex_code){
//print '"' . $word . '" sounds like ' . $str;
$array = array('word' => $word, 'allWords' => $allWords);
return $array;
}
And then just retrieve the values out of $array like so:
$filledArray = findSpellings($word, $allWords);
echo "You typed".$filledArray['word'][0]."<br/>";
echo "Were you looking for one of the following words?<br/>";
foreach($filledArray['allWords'] as $value)
{
echo $value;
}

complex regex with preg_replace, replace a word not inside [ and ]

I'm having trouble finding a correct regex to achieve what I want.
I have a sentence like that :
Hi, my name is Stan, you are welcome, hello.
and I would like to transform it like that :
[hi|hello|welcome], my name is [stan|jack] you are [hi|hello|welcome] [hi|hello|welcome].
Right now my regex is half working, because somes words are not replaced, and those replaced are deleting some characters
Here is my test code
<?php
$test = 'Hi, my name is Stan, you are welcome, hello.';
$words = array(
array('hi', 'hello', 'welcome'),
array('stan', 'jack'),
);
$result = $test;
foreach ($words as $group) {
if (count($group) > 0) {
$replacement = '[' . implode('|', $group) . ']';
foreach ($group as $word) {
$result = preg_replace('#([^\[])' . $word . '([^\]])#i', $replacement, $result);
}
}
}
echo $test . '<br />' . $result;
Any help will be appreciated
The regex you are using is overcomplicated. You simply need to use a regex substitution using regular brackets ():
<?php
$test = 'Hi, my name is Stan, you are welcome, hello.';
$words = array(
array('hi', 'hello', 'welcome'),
array('stan', 'jack'),
);
$result = $test;
foreach ($words as $group) {
if (count($group) > 0) {
$imploded = implode('|', $group);
$replacement = "[$imploded]";
$search = "($imploded)";
$result = preg_replace("/$search/i", $replacement, $result);
}
}
echo $test . '<br />' . $result;
Your regular expression:
'#([^\[])' . $word . '([^\]])#i'
matches one character before and after $word as well. And as they do, they replace it. So your replacement string needs to reference these parts, too:
'$1' . $replacement . '$2'
Demo
preg_replace supports array as parameter. No need to iterate with a loop.
$s = array("/(hi|hello|welcome)/i", "/(stan|jack)/i");
$r = array("[hi|hello|welcome]", "[stan|jack]");
preg_replace($s, $r, $str);
or dynamically
$test = 'Hi, my name is Stan, you are welcome, hello.';
$s = array("hi|hello|welcome", "stan|jack");
$r = array_map(create_function('$a','return "[$a]";'), $s);
$s = array_map(create_function('$a','return "/($a)/i";'), $s);
echo preg_replace($s, $r, $str);
//[hi|hello|welcome], my name is [stan|jack], you are [hi|hello|welcome], [hi|hello|welcome].

php string in to javascript code with comma except last string

I'm using a javascript plugin this is the line which I need help from u
<script type="text/javascript">
$('ul#news').newswidget({ source: ['http://rss.news.yahoo.com/rss/us', 'http://rss.news.yahoo.com/rss/world', 'http://feeds.bbci.co.uk/news/rss.xml'],
I would like to add URL data from MySQL
I'm using it with while loop like this
$('ul#news').newswidget({ source:[<?php
while($rssrow = mysql_fetch_array($rss))
{
echo "'"."$rssrow[rss_name]"."'".",";
}
?>],
It doesn't work properly :(.
I need to get like URL,URL,RUL like this.
that means no comma for the last one
any one please help me
You can actually do that pretty easily by a simple reorganization:
if($rssrow = mysql_fetch_array($rss))
{
echo "'".$rssrow['rss_name']."'";
while($rssrow = mysql_fetch_array($rss))
{
// note no quotes -- they are redundant
// prepend the comma
echo ","."'".$rssrow['rss_name']."'";
}
}
It does make for an extra step for the reader, but it does have the benefit of not needing substring, a new array, or a flag.
You could just build the string and remove the last comma:
$result = '';
while($rssrow = mysql_fetch_array($rss))
{
$result .= "'"."$rssrow[rss_name]"."'".",";
}
echo ($result != '') ? substr($result, 0, -1) : "''";
OR use implode():
$result = array();
while($rssrow = mysql_fetch_array($rss))
{
$result[] = $rssrow[rss_name];
}
echo "'" . implode($result, "','") . "'";
(both of these methods will output '' if the result set is empty.)
$urls = "";
while($rssrow = mysql_fetch_array($rss))
{
$urls.= "'$rssrow[rss_name]',";
}
echo substr($urls, 0, -1);
I wonder why no comment points out that you should definitely escape your output. If an entry contains a ', all solutions aside from Dmitry F’s first will break badly.
$('ul#news').newswidget({ source:[<?php
$arr = array();
while($rssrow = mysql_fetch_array($rss))
{
$arr[] = '"' . str_replace('"', '\"', $rssrow['rss_name']) . '"';
}
echo implode(',', $arr);
?>],
here is a little bit different approach:
<?php
$news = array(
'source' => array(
'http://example.com',
'http://example.com'
)
);
$news_json = json_encode($news);
?>
<script>
$('ul#news').newswidget(<?php echo $news_json; ?>);
</script>
another variation:
$url = array();
while($rssrow = mysql_fetch_array($rss))
{
$url[] = '"' . $rssrow['rss_name'] . '"';
}
echo implode(',', $url);

Categories