I'm currently using str_replace to remove a usrID and the 'comma' immediately after it:
For example:
$usrID = 23;
$string = "22,23,24,25";
$receivers = str_replace($usrID.",", '', $string); //Would output: "22,24,25"
However, I've noticed that if:
$usrID = 25; //or the Last Number in the $string
It does not work, because there is not a trailing 'comma' after the '25'
Is there a better way I can be removing a specific number from the string?
Thanks.
YOu could explode the string into an array :
$list = explode(',', $string);
var_dump($list);
Which will give you :
array
0 => string '22' (length=2)
1 => string '23' (length=2)
2 => string '24' (length=2)
3 => string '25' (length=2)
Then, do whatever you want on that array ; like remove the entry you don't want anymore :
foreach ($list as $key => $value) {
if ($value == $usrID) {
unset($list[$key]);
}
}
var_dump($list);
Which gives you :
array
0 => string '22' (length=2)
2 => string '24' (length=2)
3 => string '25' (length=2)
And, finally, put the pieces back together :
$new_string = implode(',', $list);
var_dump($new_string);
And you get what you wanted :
string '22,24,25' (length=8)
Maybe not as "simple" as a regex ; but the day you'll need to do more with your elements (or the day your elements are more complicated than just plain numbers), that'll still work :-)
EDIT : and if you want to remove "empty" values, like when there are two comma, you just have to modifiy the condition, a bit like this :
foreach ($list as $key => $value) {
if ($value == $usrID || trim($value)==='') {
unset($list[$key]);
}
}
ie, exclude the $values that are empty. The "trim" is used so $string = "22,23, ,24,25"; can also be dealt with, btw.
Another issue is if you have a user 5 and try to remove them, you'd turn 15 into 1, 25 into 2, etc. So you'd have to check for a comma on both sides.
If you want to have a delimited string like that, I'd put a comma on both ends of both the search and the list, though it'd be inefficient if it gets very long.
An example would be:
$receivers = substr(str_replace(','.$usrID.',', ',', ','.$string.','),1,-1);
An option similar to Pascal's, although I think a bit simipler:
$usrID = 23;
$string = "22,23,24,25";
$list = explode(',', $string);
$foundKey = array_search($usrID, $list);
if ($foundKey !== false) {
// the user id has been found, so remove it and implode the string
unset($list[$foundKey]);
$receivers = implode(',', $list);
} else {
// the user id was not found, so the original string is complete
$receivers = $string;
}
Basically, convert the string into an array, find the user ID, if it exists, unset it and then implode the array again.
I would go the simple way: add commas around your list, replace ",23," with a single comma then remove extra commas. Fast and simple.
$usrID = 23;
$string = "22,23,24,25";
$receivers = trim(str_replace(",$usrID,", ',', ",$string,"), ',');
With that said, manipulating values in a comma separated list is usually sign of a bad design. Those values should be in an array instead.
Try using preg:
<?php
$string = "22,23,24,25";
$usrID = '23';
$pattern = '/\b' . $usrID . '\b,?/i';
$replacement = '';
echo preg_replace($pattern, $replacement, $string);
?>
Update: changed $pattern = '/$usrID,?/i'; to $pattern = '/' . $usrID . ',?/i';
Update2: changed $pattern = '/' . $usrID . ',?/i to $pattern = '/\b' . $usrID . '\b,?/i' to address onnodb's comment...
Simple way (providing all 2 digit numbers):
$string = str_replace($userId, ',', $string);
$string = str_replace(',,','', $string);
Related
I have some date values (each with a trailing = sign) stored as a &-delimited string.
My $_POST['dates'] string looks like this:
23.08.18=&22.08.18=&21.08.18=
I'm trying the following PHP code to extract the dates before inserting them into my database table. The code is currently not working.
foreach(explode('&', $_POST['dates']) as $value)
{
$value1 = explode('=', $value);
foreach ($value1 as $x) {
}
}
How can I isolate the date values?
The function that you might be looking for is parse_str(). You have a valid query string (well, kind of) with keys but no values, so you merely need to parse it and isolate the keys(dates). Unfortunately, the parser converts your dots to underscores.
Code: (Demo)
$string = '23.08.18=&22.08.18=&21.08.18=';
parse_str($string, $out);
var_export(array_keys($out));
Output:
array (
0 => '23_08_18',
1 => '22_08_18',
2 => '21_08_18',
)
And of course, you can repair the modified date values with str_replace(). See this demo.
Or if you want to disregard parse_str(), you can use just one regex call that divides the string on = followed by an optional &:
Code: (Demo)
$string = '23.08.18=&22.08.18=&21.08.18=';
var_export(preg_split('~=&?~', $string, -1, PREG_SPLIT_NO_EMPTY));
Output:
array (
0 => '23.08.18',
1 => '22.08.18',
2 => '21.08.18',
)
Or without regex, just trim the last = and explode on =&: (Demo)
$string = '23.08.18=&22.08.18=&21.08.18=';
var_export(explode('=&', rtrim($string, '=')));
// same output as preg_split()
<?php
$data = '23.08.18=&22.08.18=&21.08.18=';
//$delimiters has to be array
//$string has to be array
function multiexplode ($delimiters,$string) {
$ary = explode($delimiters[0],$string);
array_shift($delimiters);
if($delimiters != NULL) {
foreach($ary as $key => $val) {
$ary[$key] = multiexplode($delimiters, $val);
}
}
return $ary;
}
$exploded = multiexplode(array("=","&"),$data);
var_dump($exploded);
The result should be:
array (size=3)
0 => string '23.08.18' (length=8)
2 => string '22.08.18' (length=8)
4 => string '21.08.18' (length=8)
We need to use array_filter.
http://php.net/manual/en/function.explode.php
[EDIT] mickmackusa's answer is the right tool for parse url parameters into variables.
I have a problem - hope you can help.
My users will enter a string like this:
'dt', 'time_hour', 'loc', 'protocol_category', 'service_identifier', 'mcc', 'imsi', 'service_dl_bytes', 'service_ul_ bytes'
Depending on their other inputs, I then remove two fields from this list (for example, service_identifier and service_dl_bytes)
This leaves lots of stray commas in the string.
I need some logic that says:
- there can only be one consecutive comma
- there should not be a comma as the last character
- comma, space comma is also not permitted
Basically, the format has to be 'input', 'input2', 'input3'
Can anyone help me .. i tried with the below, but it doesn't work in all use cases
elseif ($df3aggrequired == "YES" and $df3agg2required == "NO" ) {
#remove spaces from select statement
$df3group0v2 = str_replace($df3aggfield, '', $df3select);
#replace aggfield1 with null
$df3group1v2 = str_replace(' ', '', $df3group0v2);
#replace instances of ,, with ,
$df3group3v2 = preg_replace('/,,+/', ',', $df3group1v2);
$finalstring0df3v2 = rtrim($df3group3v2, ',');
$finalstring1df3v2 = str_replace('\'\'', '', $finalstring0df3v2);
$finalstringdf3v2 = str_replace('.,', '', $finalstring1df3v2);
$finalstringdf31v2 = str_replace(',,', ',', $finalstringdf3v2);
$finalcleanup = preg_replace('/,,+/', ',', $finalstringdf31v2);
echo"\\<br> .groupBy(";
echo "$finalcleanup";
echo ")";
I also think that string replacements can cause issues, so went for a similar process to geoidesic, this code tries to stick with the fields being a CSV list, and removes the quotes round them as part of the decoding, but also puts them back again in the result.
$fields = "'dt', 'time_hour', 'loc', 'protocol_category', 'service_identifier', 'mcc', 'imsi', 'service_dl_bytes', 'service_ul_ bytes'";
$removeFields = true ;
$fieldList = str_getcsv($fields, ",", "'");
if ( $removeFields == true ) {
if ( ($key = array_search('loc', $fieldList)) !== false ) {
unset ( $fieldList[$key] );
}
$fields = "'".implode("', '", $fieldList)."'";
}
echo $fields;
The example removes the 'loc' field, but this can be modified to remove any fields required.
The final output is (assuming 'loc' is removed)...
'dt', 'time_hour', 'protocol_category', 'service_identifier', 'mcc', 'imsi', 'service_dl_bytes', 'service_ul_ bytes'
Whatever your string after removing process is, you may want to run a single preg_replace over it using a positive lookahead:
^\s*(,\s*)*|,\s*(?=,|$)
Live demo
Breakdown:
^\s*(,\s*)* Match unwanted commas at beginning
| Or
,\s*(?=,|$) Match consecutive commas or trailing ones
PHP code:
$string = preg_replace('~^\s*(,\s*)*|,\s*(?=,|$)~', '', $string);
You'd better consider removing unwanted commas while removing words.
If it is a comma-separated list, then don't use str_replace. Turn the string into an array first by splitting it on the commas:
$myArray = explode(',' $myString);
Then remove the parts of the array you don't want and make it a string again:
$fieldsToDelete = ["service_identifier", "service_dl_bytes"];
$newArray = [];
foreach($myArray as $key => $value) {
if(!in_array($value, $fieldsToDelete) {
array_push($newArray, $value)
}
}
$newString = implode(',', $newArray)
The following code works on the index of the fields you want to remove.
Works the same as the answer written by #geoidesic but uses index of field in string instead of a string match.
$user_input = "'dt', 'time_hour', 'loc', 'protocol_category', 'service_identifier', 'mcc', 'imsi', 'service_dl_bytes', 'service_ul_ bytes'";
$input_array = explode(',', $user_input);
// 4 = 'service_indentifier'
// 8 = 'service_ul_ bytes'
$remove_input = array(4, 8);
foreach($remove_input as $array_index) {
unset($input_array[$array_index]);
}
$parsed_input = implode(',', $input_array);
var_dump($parsed_input);
// Output: string(80) "'dt', 'time_hour', 'loc', 'protocol_category', 'mcc', 'imsi', 'service_dl_bytes'"
You have try with
$var = preg_replace(["/'[\s,]*,[\s,]*'/", "/^[\s,]*|[\s,]*$/"], ["', '", ""], $var);
It can help!
I have got a variable and an array (can be a variable as well) which need to be compared. I know how to compare two strings, but I don't know how to output the words which haven't been found. Also the words which haven't been found need to be in a variable so that I can use them later on.
$mystring = array('Net 40', 'Net 44', 'Priv 40');
$findme = 'Net 44';
if( strpos($mystring, $findme) !== false ) echo $findme." has been found in the string";
EDIT
I shall rephrase my question: How to compare two variables and output all words which haven't been found.
You could use array_diff to find the words that remain after you have successfully matched a word with one in a list:
$mystring = array('Net40', 'Net44', 'Priv40');
$findme = 'Net44';
echo "<br>list of words before: " . implode(",", $mystring);
$mystring = array_diff($mystring, array($findme));
echo "<br>list of words after: " . implode(",", $mystring);
Output:
list of words before: Net40,Net44,Priv40
list of words after: Net40,Priv40
strpos check that your second parameter is in the first parameter?
e.g.
strpos("This is", "is")
this checks that 'is' is in the string or not. If you want to check the result is in array or not please do as follows
if(in_array($findme,mystring)) echo $findme." has been found in the string";
First, you should not use strpos with an array and a string.
You could make something like this:
$mystring = array('Net 40', 'Net 44', 'Priv 40');
$findme = 'Net 44';
$size = count($mystring)
$notFound = array();
for($i = 0; $i < $size; $i++)
{
if($mystring[$i] === $findme)
{
echo $findme." has been found in the string (actually array)";
}
else
{
array_push($notFound, $mystring[$i]);
}
}
If mystring is actually supposed to be a string this code has to look a little bit different. I went with what you provided.
Solution with arrays. If your have strings, you can convert them to array with explode function.
<?php
$mystring = array('Net40', 'Net44', 'Priv40');
$findme = array('Net44');
$result=array_diff($mystring,$findme);
//$result is an array of elements that was in $mystring but not in $findme
print_r($result);
?>
Haven't been found is a little ambiguous, just be careful:
<?php
$haystack = array('Net40', 'Net44', 'Priv40');
$needles = array('Net44', 'NetBsd');
var_dump(array_diff($haystack, $needles));
var_dump(array_diff($needles, $haystack));
var_dump(array_intersect($haystack, $needles));
Output:
array (size=2)
0 => string 'Net40' (length=5)
2 => string 'Priv40' (length=6)
array (size=1)
1 => string 'NetBsd' (length=6)
array (size=1)
1 => string 'Net44' (length=5)
I have a string stored in a variable, this string may appear in the next ways:
$sec_ugs_exp = ''; //Empty one
$sec_ugs_exp = '190'; //Containing the number I want to delete (190)
$sec_ugs_exp = '16'; //Containing only a number, not the one Im looking for
$sec_ugs_exp = '12,159,190'; // Containing my number at the end (or in beginning too)
$sec_ugs_exp = '15,190,145,86'; // Containing my number somewhere in the middle
I need to delete the 190 number if it exists and deleting also the comma attached after it unless my number is at the end or it is alone(there is no commas in that case)
So in the examples I wrote before, I need to get a return like this:
$sec_ugs_exp = '';
$sec_ugs_exp = '';
$sec_ugs_exp = '16';
$sec_ugs_exp = '12,159';
$sec_ugs_exp = '15,145,86';
Hope I explained myself, sorry about my English. I tried using preg_replace and some other ways, but I always failed in detecting the comma.
My final attempt not using regex:
$codes = array_flip(explode(",", $sec_ugs_exp));
unset($codes[190]);
$sec_ugs_exp = implode(',', array_keys($codes));
A simple regex should do the trick: /(190,?)/:
$newString = preg_replace('/(190,?)/', '', $string);
Demo: http://codepad.viper-7.com/TIW9D6
Or if you want to prevent matches like:
$sec_ugs_exp = '15,1901,86';
^^^
You could use:
(190(,|$))
Quick and dirty, but should work for you:
str_replace(array(",190","190,","190"), "", $sec_ugs_exp);
Note the order in the array is important.
$array = explode ( ',' , $sec_ugs_exp );
foreach ( $array AS $key => $number )
{
if ( $number == 190 )
{
unset($array[$key]);
}
}
$sec_ugs_exp = implode ( ',' , $array );
This will work if a number if 1903 or 9190
None of the answers here account for numbers beginning or ending with 190.
$newString = trim(str_replace(',,', ',', preg_replace('/\b190\b/', '', $string)), ',');
try
str_replace('190,', '', $sec_ugs_exp);
str_replace('190', '', $sec_ugs_exp);
or
str_replace('190', '', $sec_ugs_exp);
str_replace(',,' ',', $sec_ugs_exp);
if there are no extra spaces in your string
I want to convert all texts in a string into html entities but preserving the HTML tags, for example this:
<p><font style="color:#FF0000">Camión español</font></p>
should be translated into this:
<p><font style="color:#FF0000">Camión español</font></p>
any ideas?
You can get the list of correspondances character => entity used by htmlentities, with the function get_html_translation_table ; consider this code :
$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);
(You might want to check the second parameter to that function in the manual -- maybe you'll need to set it to a value different than the default one)
It will get you something like this :
array
' ' => string ' ' (length=6)
'¡' => string '¡' (length=7)
'¢' => string '¢' (length=6)
'£' => string '£' (length=7)
'¤' => string '¤' (length=8)
....
....
....
'ÿ' => string 'ÿ' (length=6)
'"' => string '"' (length=6)
'<' => string '<' (length=4)
'>' => string '>' (length=4)
'&' => string '&' (length=5)
Now, remove the correspondances you don't want :
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
Your list, now, has all the correspondances character => entity used by htmlentites, except the few characters you don't want to encode.
And now, you just have to extract the list of keys and values :
$search = array_keys($list);
$values = array_values($list);
And, finally, you can use str_replace to do the replacement :
$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_out);
And you get :
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=84)
Which looks like what you wanted ;-)
Edit : well, except for the encoding problem (damn UTF-8, I suppose -- I'm trying to find a solution for that, and will edit again)
Second edit couple of minutes after : it seem you'll have to use utf8_encode on the $search list, before calling str_replace :-(
Which means using something like this :
$search = array_map('utf8_encode', $search);
Between the call to array_keys and the call to str_replace.
And, this time, you should really get what you wanted :
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=70)
And here is the full portion of code :
$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
$search = array_keys($list);
$values = array_values($list);
$search = array_map('utf8_encode', $search);
$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_in, $str_out);
And the full output :
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=58)
string '<p><font style="color:#FF0000">Camión español</font></p>' (length=70)
This time, it should be ok ^^
It doesn't really fit in one line, is might not be the most optimized solution ; but it should work fine, and has the advantage of allowing you to add/remove any correspondance character => entity you need or not.
Have fun !
Might not be terribly efficient, but it works
$sample = '<p><font style="color:#FF0000">Camión español</font></p>';
echo htmlspecialchars_decode(
htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
, ENT_NOQUOTES
);
This is optimized version of the accepted answer.
$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);
$string = strtr($string, $list);
No solution short of a parser is going to be correct for all cases. Yours is a good case:
<p><font style="color:#FF0000">Camión español</font></p>
but do you also want to support:
<p><font>true if 5 < a && name == "joe"</font></p>
where you want it to come out as:
<p><font>true if 5 < a && name == "joe"</font></p>
Question: Can you do the encoding BEFORE you build the HTML. In other words can do something like:
"<p><font>" + htmlentities(inner) + "</font></p>"
You'll save yourself lots of grief if you can do that. If you can't, you'll need some way to skip encoding <, >, and " (as described above), or simply encode it all, and then undo it (eg. replace('<', '<'))
one-line solution with NO translation table or custom function required:
i know this is an old question, but i recently had to import a static site into a wordpress site and had to overcome this issue:
here is my solution that does not require fiddling with translation tables:
htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );
when applied to the OP's string:
<p><font style="color:#FF0000">Camión español</font></p>
output:
<p><font style="color:#FF0000">Camión español</font></p>
when applied to Luca's string:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>
output:
<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>
This is a function I've just written which solves this problem in a very elegant way:
First of all, the HTML tags will be extracted from the string, then htmlentities() is executed on every remaining substring and after that the original HTML tags will be inserted at their old position thus resulting in no alternation of the HTML tags. :-)
Have fun:
function htmlentitiesOutsideHTMLTags ($htmlText)
{
$matches = Array();
$sep = '###HTMLTAG###';
preg_match_all("#<[^>]*>#", $htmlText, $matches);
$tmp = preg_replace("#(<[^>]*>)#", $sep, $htmlText);
$tmp = explode($sep, $tmp);
for ($i=0; $i<count($tmp); $i++)
$tmp[$i] = htmlentities($tmp[$i]);
$tmp = join($sep, $tmp);
for ($i=0; $i<count($matches[0]); $i++)
$tmp = preg_replace("#$sep#", $matches[0][$i], $tmp, 1);
return $tmp;
}
Based on the answer of bflesch, I did some changes to manage string containing less than sign, greater than sign and single quote or double quotes.
function htmlentitiesOutsideHTMLTags ($htmlText, $ent)
{
$matches = Array();
$sep = '###HTMLTAG###';
preg_match_all(":</{0,1}[a-z]+[^>]*>:i", $htmlText, $matches);
$tmp = preg_replace(":</{0,1}[a-z]+[^>]*>:i", $sep, $htmlText);
$tmp = explode($sep, $tmp);
for ($i=0; $i<count($tmp); $i++)
$tmp[$i] = htmlentities($tmp[$i], $ent, 'UTF-8', false);
$tmp = join($sep, $tmp);
for ($i=0; $i<count($matches[0]); $i++)
$tmp = preg_replace(":$sep:", $matches[0][$i], $tmp, 1);
return $tmp;
}
Example of use:
$string = '<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>';
$string_entities = htmlentitiesOutsideHTMLTags($string, ENT_QUOTES | ENT_HTML401);
var_dump( $string_entities );
Output is:
string '<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>' (length=150)
You can pass any ent flag according to the htmlentities manual