php str_replace only replacing the 1st value in the needle array - php

I have been using this function for some time now but this is the 1st time I am having this weird trouble with PHP's str_replace function. Here is my code...
$e2p_perline = explode(',', $e2p_wrd_rplc);
$e2p_words = array();
$e2p_words_2b = array();
$e2p_loopcounter = 0;
foreach($e2p_perline as $line){
$e2p_line_words = explode('-', $line);
$e2p_words[$e2p_loopcounter] = $e2p_line_words[0];
$e2p_words_2b[$e2p_loopcounter] = $e2p_line_words[1];
$e2p_loopcounter++;
}
$e2p_message = str_replace($e2p_words, $e2p_words_2b, $e2p_message);
$e2p_wrd_rplc is a string loaded from the database using get_option() function of wordpress. String data in this format c*sh-cash, v*gra-viagra, s3x-sex,....
$e2p_words is an array filled with the words to be replaced and $e2p_words_2b is an array filled with replacement words.
Lets suppose we have
e2p_words is (c*sh, v*agra, s3x)
e2p_words_2b is (cash, viagra, sex)
Now when I run this, only the 1st word c*sh is replaced with cash. Rest of the e2p_words occurrences in e2p_message stay the same.
I am getting no errors or warnings either.

This works for me :
<?php
$e2p_words = array("c*sh", "v*agra", "s3x");
$e2p_words_2b = array("cash", "viagra", "sex");
$e2p_message = "Get a v*agra, or you'll have to pay c*sh for some real s3x.";
$e2p_message = str_replace($e2p_words, $e2p_words_2b, $e2p_message);
echo $e2p_message;
?>
Output :
Get a viagra, or you'll have to pay cash for some real sex.

Related

how to partially mask/hide email address using PHP

Im trying to achieve the following with PHP
sample#gmail.com => s*****#gmail.com
sa#yahoo.com => **#yahoo.com
sampleaddress#hotmail.com => samplead*****#hotmail.com
I want to hide last five characters in the portion that stays before '#'
I can write long code to do this by splitting and then replacing based on lengths, but Im sure there must be an easy way to do this using PHP functions, any help please?
UPDATE:
Im adding my code here, Im sure its not efficient, and thats the reason Im asking it here
$email = 'sampleuser#gmail.com';
$star_string = '';
$expl_set = explode('#',$email);
if(strlen ($expl_set[0]) > 5){$no_stars = 5; }else{$no_stars = strlen ($expl_set[0]); }
for($i=0;$i<$no_stars; $i++)
{
$star_string.='*';
}
$masked_email = substr($expl_set[0], 0, -5).$star_string.'#'.$expl_set[1];
You can wrap it into a function, making it easier to call multiple times.
Basically, split the address and the domain, replace $mask number of characters in the end of the string (default 5) with *, or the length of the address if it's shorter than the amount of masked characters.
function mask_email($email, $masks = 5) {
$array = explode("#", $email);
$string_length = strlen($array[0]);
if ($string_length < $masks)
$masks = $string_length;
$result = substr($array[0], 0, -$masks) . str_repeat('*', $masks);
return $result."#".$array[1];
}
The above would be used like this
echo mask_email("test#test.com")."\n";
echo mask_email("longeremail#test.com");
which would ouput this
****#test.com
longer*****#test.com
You can also specify the number you want filtered by using the second parameter, which is optional.
echo mask_email("longeremail#test.com", 2); // Output: longerema**#test.com
Live demo

PHP read value cURL page

I'm a fan of Bitcoins and all other alternative coins, so what I am trying to make is a page with all my coins I own, and shows the latest value of each coin.
So what I've got so far is a cURL that gets the content of a website, in this case it is cryptorush.in.
The output of the cURL is:
21 / BTC
13.22000001
42 / BTC
112.10000000
Etc.
So I thought it would be a nice way to recognize "21 / BTC" for example and read the latest value at the next line.
$curlPage is my cURL page.
if (strpos($curlPage,'21 / BTC') !== false) {
//do something
}
Output:
13.22000001
But I really have no idea on how to do this, so I hope anyone could answer my question.
You can use a combination of regexp and the explode function. Please note that this is dependent upon the actual coding of the page you are requesting with cURL, as I am looking at the values being exploded by two returns - \n\n
$curlPage = "21 / BTC \n13.22000001\n\n42 / BTC \n112.10000000";
$arr = explode("\n\n", $curlPage);
foreach($arr as $key)
{
list($top, $bottom) = explode("\n", $key);
$top = preg_replace("/[^0-9]/", "", $top);
if($top == "21") echo($bottom);
}
The first line shows what my value for $curlPage is (for testing it). This should be equal to the contents of the page (provided the contents are what you posted and each section is separated by two line breaks (\n\n)
The two important variables in the foreach() statement is $top and $bottom. $top will be equal to the number, like 21. And the $bottom variable will be equal to the bottom number like 13.22000001

How to split content into equal parts then write to file in PHP

I have been reading/testing examples since last night, but the cows never came home.
I have a file with (for example) approx. 1000 characters in one line and want to split it into 10 equal parts then write back to the file.
Goal:
1. Open the file in question and read its content
2. Count up to 100 characters for example, then put a line break
3. Count 100 again and another line break, and so on till it's done.
4. Write/overwrite the file with the new split content
For example:
I want to turn this => KNMT2zSOMs4j4vXsBlb7uCjrGxgXpr
Into this:
KNMT2zSOMs
4j4vXsBlb7
uCjrGxgXpr
This is what I have so far:
<?php
$MyString = fopen('file.txt', "r");
$MyNewString;
$n = 100; // How many you want before seperation
$MyNewString = substr($MyString,0,$n);
$i = $n;
while ($i < strlen($MyString)) {
$MyNewString .= "\n"; // Seperator Character
$MyNewString .= substr($MyString,$i,$n);
$i = $i + $n;
}
file_put_contents($MyString, $MyNewString);
fclose($MyString);
?>
But that is not working quite the way I anticipated.
I realize that there are other similiar questions like mine, but they were not showing how to read a file, then write back to it.
<?php
$str = "aonoeincoieacaonoeincoieacaonoeincoieacaonoeincoieacaonoeincoieacaon";
$pieces = 10;
$ch = chunk_split($str, $pieces);
$piece = explode("\n", $ch);
foreach($piece as $line) {
// write to file
}
?>
http://php.net/manual/en/function.chunk-split.php
Hold on here. You're not giving a file name/path to file_put_contents();, you're giving a file handle.
Try this:
file_put_contents("newFileWithText.txt", $MyNewString);
You see, when doing $var=fopen();, you're giving $var a value of a handle, which is not meant to be used with file_put_contents(); as it doesnt ask for a handle, but a filename instead. So, it should be: file_put_contents("myfilenamehere.txt", "the data i want in my file here...");
Simple.
Take a look at the documentation for str_split. It will take a string and split it into chunks based on length, storing each chunk at a separate index in an array that it returns. You can then iterate over the array adding a line break after each index.

Get the two most frequent words within several strings

I have a list of phrases and I want to know which two words occurred the most often in all of my phrases.
I tried playing with regex and other codes and I just cannot find the right way to do this.
Can anyone help?
eg:
I am purchasing a wallet
a wallet for 20$
purchasing a bag
I'd know that
a wallet occurred 2 times
purchasing a occurred 2 times
<?
$string = "I am purchasing a wallet a wallet for 20$ purchasing a bag";
//split string into words
$words = explode(' ', $string);
//make chunks block ie [0,1][2,3]...
$chunks = array_chunk($words, 2);
//remove first array element
unset($words[0]);
//make chunks block ie [0,1][2,3]...
//but since first element is removed , the real block will be [1,2][3,4]...
$alternateChunks = array_chunk($words, 2);
//merge both chunks
$totalChunks = array_merge($chunks,$alternateChunks);
$finalChunks = array();
foreach($totalChunks as $t)
{
//change the inside chunk to pharse using +
//+ can be replaced to space, if neeced
//to keep associative working + is used instead of white space
$finalChunks[] = implode('+', $t);
}
//count the words inside array
$result = array_count_values($finalChunks);
echo "<pre>";
print_r($result);
I hesitate to suggest this, as it's an extremely brute force way to go about it:
Take your string of words, explode it using the explode(" ", $string); command, then run it through a for loop checking every two word combination against every two words in the string.
$string = "I am purchasing a wallet a wallet for 20$ purchasing a bag";
$words = explode(" ", $string);
for ($t=0; $t<count($string); $t++)
{
for ($i=0; $i<count($string); $i++)
{
if (($words[$t] . words[$t+1]) == ($words[$i] . $word[$i+1])) {$count[$words[$i].$words[$i+1]]++}
}
}
So the nested for loop steps in, grabs the first two words, compares them to each other set of two consecutive words, then grabs the next two words and does it again. Every answer will have an answer of at least 1 (it will always match itself) but sorting the resulting array by size will give you the most repeated values.
Note that this will run (n-1)*(n-1) iterations, which could get unwieldy FAST.
Place them all into an array, and access them by the current word index and next word index.
I think this should do the trick. It will grab pairs of words, unless you are at the end of the string, where you'll get only one word.
$str = "I purchased a wallet because I wanted a wallet a wallet a wallet";
$words = explode(" ", $str);
$array_results = array();
for ($i = 0; $i<count($words); $i++) {
if ($i < count($words)-1) {
$pair = $words[$i] . " " . $words[$i+1]; echo $pair . "\n";
// Have to check if the key is in use yet to avoid a notice
$array_results[$pair] = isset($array_results[$pair]) ? $array_results[$pair] + 1 : 1;
}
// At the end of the array, just use a single word
else $array_results[$words[$i]] = isset($array_results[$words[$i]]) ? $array_results[$words[$i]] + 1 : 1;
}
// Sort the results
// use arsort() instead to get the highest first
asort($array_results);
// Prints:
Array
(
[I wanted] => 1
[wanted a] => 1
[wallet] => 1
[because I] => 1
[wallet because] => 1
[I purchased] => 1
[purchased a] => 1
[wallet a] => 2
[a wallet] => 4
)
Update changed ++ to +1 above since it wasn't working when tested...
Try to put it with explode into an array and count the values with array_count_values.
<?php
$text = "whatever";
$text_array = explode( ' ', $text);
$double_words = array();
for($c = 1; $c < count($text_array); $c++)
{
$double_words[] = $text_array[$c -1] . ' ' . $text_array[$c];
}
$result = array_count_values($double_words);
?>
I updated it now to two word version. Does this work for you?
array(9) {
["I am"]=> int(1)
["am purchasing"]=> int(1)
["purchasing a"]=> int(2)
["a wallet"]=> int(2)
["wallet a"]=> int(1)
["wallet for"]=> int(1)
["for 20$"]=> int(1)
["20$ purchasing"]=> int(1)
["a bag"]=> int(1)
}
Since you used the excel tag, I thought I'd give it a shot, and it's actually really easy.
Split string using space as delimiter. Data > Text to Columns... > Delimited > Delimiter: Space. Each word is now in its own cell.
Transpose the result (not strictly required but much easier to visualize). Copy, Edit > Paste Special... > Transpose.
Make cells containing consecutive word pairs. So if your words are in cells B5:B15, cell C5 should be =B5&" "&B6 (and drag down).
Count occurence of each word pair: In cell D5, =COUNTIF($C$5:$C$15,"="&C5), drag down.
Highlight the winner(s). Select C5:D15, Format > Conditional Formatting... > Formula Is =$D5=MAX($D$5:$D$15) and choose e.g. a yellow background.
Note that there is some inefficiency in step 4 because the count of each word pair will be calculated multiple times if that word pair occurs multiple times. If this is a concern, then you can first make a list of unique word pairs using Data > Filter > Advanced Filter... > Unique records only.
An automated VBA solution could easily be crafted by recording a macro of the above followed by some minor editing.
One way to go about it is to use SPLIT or a regex to split the sentences into words and store each into an array. Then take the array and create a dictionary object. When you add a term to the dictionary, if it's already there, add 1 to the .value to tally the count.
Here is some example code (far from perfect as it's just to show the overlying concept) that will take all the string in column A and generate a word frequency list in columns B and C. It's not exactly what you want, but should give you some ideas on how you can go about doing it I hope:
Sub FrequencyList()
Dim vArray As Variant
Dim myDict As Variant
Set myDict = CreateObject("Scripting.Dictionary")
Dim i As Long
Dim cell As range
With myDict
For Each cell In range("A1", cells(Rows.count, "A").End(xlUp))
vArray = Split(cell.Value, " ")
For i = LBound(vArray) To UBound(vArray)
If Not .exists(vArray(i)) Then
.Add vArray(i), 1
Else
.Item(vArray(i)) = .Item(vArray(i)) + 1
End If
Next
Next
range("B1").Resize(.count).Value = Application.Transpose(.keys)
range("C1").Resize(.count).Value = Application.Transpose(.items)
End With
End Sub

Split a large string into an array, but the split point cannot break a tag

I wrote a script that sends chunks of text of to Google to translate, but sometimes the text, which is html source code) will end up splitting in the middle of an html tag and Google will return the code incorrectly.
I already know how to split the string into an array, but is there a better way to do this while ensuring the output string does not exceed 5000 characters and does not split on a tag?
UPDATE: Thanks to answer, this is the code I ended up using in my project and it works great
function handleTextHtmlSplit($text, $maxSize) {
//our collection array
$niceHtml[] = '';
// Splits on tags, but also includes each tag as an item in the result
$pieces = preg_split('/(<[^>]*>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
//the current position of the index
$currentPiece = 0;
//start assembling a group until it gets to max size
foreach ($pieces as $piece) {
//make sure string length of this piece will not exceed max size when inserted
if (strlen($niceHtml[$currentPiece] . $piece) > $maxSize) {
//advance current piece
//will put overflow into next group
$currentPiece += 1;
//create empty string as value for next piece in the index
$niceHtml[$currentPiece] = '';
}
//insert piece into our master array
$niceHtml[$currentPiece] .= $piece;
}
//return array of nicely handled html
return $niceHtml;
}
Note: haven't had a chance to test this (so there may be a minor bug or two), but it should give you an idea:
function get_groups_of_5000_or_less($input_string) {
// Splits on tags, but also includes each tag as an item in the result
$pieces = preg_split('/(<[^>]*>)/', $input_string,
-1, PREG_SPLIT_DELIM_CAPTURE);
$groups[] = '';
$current_group = 0;
while ($cur_piece = array_shift($pieces)) {
$piecelen = strlen($cur_piece);
if(strlen($groups[$current_group]) + $piecelen > 5000) {
// Adding the next piece whole would go over the limit,
// figure out what to do.
if($cur_piece[0] == '<') {
// Tag goes over the limit, just put it into a new group
$groups[++$current_group] = $cur_piece;
} else {
// Non-tag goes over the limit, split it and put the
// remainder back on the list of un-grabbed pieces
$grab_amount = 5000 - $strlen($groups[$current_group];
$groups[$current_group] .= substr($cur_piece, 0, $grab_amount);
$groups[++$current_group] = '';
array_unshift($pieces, substr($cur_piece, $grab_amount));
}
} else {
// Adding this piece doesn't go over the limit, so just add it
$groups[$current_group] .= $cur_piece;
}
}
return $groups;
}
Also note that this can split in the middle of regular words - if you don't want that, then modify the part that begins with // Non-tag goes over the limit to choose a better value for $grab_amount. I didn't bother coding that in since this is just supposed to be an example of how to get around splitting tags, not a drop-in solution.
Why not strip the html tags from the string before sending it to google. PHP has a strip_tags() function that can do this for you.
preg_split with a good regex would do it for you.

Categories