PHP cleaning up a string of duplicated commas etc - php

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!

Related

PHP str_ireplace for array

I am trying to remove certain strings from an array of strings
$replace = array(
're: ', 're:', 're',
'fw: ', 'fw:', 'fw',
'[Ticket ID: #'.$ticket["ticketnumber"].'] ',
);
$available_subjects = array($ticket["subject"], $update["subject"]);
I tried using these loops
This replaced words like "You're" because of the "re"
foreach($replace as $r) {
$available_subjects = str_ireplace($r, '', $available_subjects);
}
And the same with this one
foreach($replace as $r) {
$available_subjects = preg_replace('/\b'.$r.'\b/i', '', $available_subjects);
}
So I want to match the whole word, and not part of words
First, I would replace Ticket IDs statically like you did:
$ticket_prefix = '[Ticket ID: #' . $ticket["ticketnumber"] . '] ';
$available_subjects = str_ireplace($ticket_prefix, '', $available_subjects);
Then, I would use a regular expression to replace re and fw:
$available_subjects = preg_replace('#\b(fw|re):?\s*\b#i', '', $available_subjects);

Edit a string which is different each time

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

Check stock tickers in string against array

Consider the following array which holds all US stock tickers, ordered by length:
$tickers = array('AAPL', 'AA', 'BRK.A', 'BRK.B', 'BAE', 'BA'); // etc...
I want to check a string for all possible matches. Tickers are written with or without a "$" concatenated to the front:
$string = "Check out $AAPL and BRK.A, BA and BAE.B - all going up!";
All tickers are to be labeled like: {TICKER:XX}. The expected output would be:
Check out {TICKER:AAPL} and {TICKER:BRK.A} and BAE.B - all going up!
So tickers should be checked against the $tickers array and matched both if they are followed by a space or a comma. Until now, I have been using the following:
preg_replace('/\$([a-zA-Z.]+)/', ' {TICKER:$1} ', $string);
so I didn't have to check against the $tickers array. It was assumed that all tickers started with "$", but this only appears to be the convention in about 80% of the cases. Hence, the need for an updated filter.
My question being: is there a simple way to adjust the regex to comply with the new requirement or do I need to write a new function, as I was planning first:
function match_tickers($string) {
foreach ($tickers as $ticker) {
// preg_replace with $
// preg_replace without $
}
}
Or can this be done in one go?
Just make the leading dollar sign optional, using ? (zero or 1 matches). Then you can check for legal trailing characters using the same technique. A better way to go about it would be to explode your input string and check/replace each substring against the ticker collection, then reconstruct the input string.
function match_tickers($string) {
$aray = explode( " ", $string );
foreach ($aray as $word) {
// extract any ticker symbol
$symbol = preg_replace( '/^\$?([A-Za-z]?\.?[A-Za-z])\W*$/', '$1', $word );
if (in_array($symbol,$tickers)) { // symbol, replace it
array_push( $replacements, preg_replace( '/^\$?([A-Za-z]?\.?[A-Za-z])(\W*)$/', '{TICKER:$1}$2', $word ) );
}
else { // not a symbol, just output it normally
array_push( $replacements, $word );
}
}
return implode( " ", $replacements );
}
I think just a slight change to your regex should do the trick:
\$?([a-zA-Z.]+)
i added "?" in front of the "$", which means that it can appear 0 or 1 times
You can use a single foreach loop on your array to replace the ticker items in your string.
$tickers = array('AAPL', 'AA', 'BRK.A', 'BRK.B', 'BAE', 'BA');
$string = 'Check out $AAPL and BRK.A, BA and BAE.B - all going up!';
foreach ($tickers as $ticker) {
$string = preg_replace('/(\$?)\b('.$ticker.')\b(?!\.[A-Z])/', '{TICKER:$2}', $string);
}
echo $string;
will output
Check out {TICKER:AAPL} and {TICKER:BRK.A}, {TICKER:BA} and BAE.B -
all going up!
Adding ? after the $ sign will also accept words, i.e. 'out'
preg_replace accepts array as a pattern, so if you change your $tickers array to:
$tickers = array('/AAPL/', '/AA/', '/BRK.A/', '/BRK.B/', '/BAE/', '/BA/');
then this should do the trick:
preg_replace($tickers, ' {TICKER:$1} ', $string);
This is according to http://php.net/manual/en/function.preg-replace.php

PHP: strip the tags off the value inside array_values()

I want to strip the tags off the value inside array_values() before imploding with tabs.
I tried with this line below but I have an error,
$output = implode("\t",strip_tags(array_keys($item)));
ideally I want to strip off the line breaks, double spaces, tabs from the value,
$output = implode("\t",preg_replace(array("/\t/", "/\s{2,}/", "/\n/"), array("", " ", " "), strip_tags(array_keys($item))));
but I think my method is not correct!
this is the entire function,
function process_data($items){
# set the variable
$output = null;
# check if the data is an items and is not empty
if (is_array($items) && !empty($items))
{
# start the row at 0
$row = 0;
# loop the items
foreach($items as $item)
{
if (is_array($item) && !empty($item))
{
if ($row == 0)
{
# write the column headers
$output = implode("\t",array_keys($item));
$output .= "\n";
}
# create a line of values for this row...
$output .= implode("\t",array_values($item));
$output .= "\n";
# increment the row so we don't create headers all over again
$row++;
}
}
}
# return the result
return $output;
}
Please let me know if you have any ideas how to fix this. Thanks!
strip_tags only works on strings, not on array input. Thus you have to apply it after implode made a string of the input.
$output = strip_tags(
implode("\t",
preg_replace(
array("/\t/", "/\s{2,}/", "/\n/"),
array("", " ", " "),
array_keys($item)
)
)
);
You'll have to test if it gives you the desired results. I don't know what the preg_replace accomplishes.
Otherwise you could use array_map("strip_tags", array_keys($item)) to have the tags removed first (if there are really any significant \t within the tags in the strings.)
(No idea what your big function is about.)
try mapping the arrays to strip_tags and trim.
implode("\t", array_map("trim", array_map("strip_tags", array_keys($item))));
Stripping the tags is easy as this:
$a = array('key'=>'array item<br>');
function fix(&$item, $key)
{
$item = strip_tags($item);
}
array_walk($a, 'fix');
print_r($a);
Of course, you can make whatever modifications you like to $item in the fix function. The change will be stored in the array.
For a multidimensional array use array_walk_recursive($a, 'fix');.
Looks like you just need to use array_map, since strip_tags expects a string, not an array.
$arr = array( "Some\tTabbed\tValue" => '1',
"Some value with double spaces" => '2',
"Some\nvalue\nwith\nnewlines" => '3',
);
$search = array("#\t#", "#\s{2,}#", "#\n#");
$replace = array("", " ", " ");
$output = implode("\t", preg_replace($search, $replace, array_map('strip_tags', array_keys($arr))));
echo $output;

PHP str_replace

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);

Categories