multiple characters replacements in string php - php

Let's say that I have the following string:
$string = 'xxyyzz';
And then I have a substitution array like this:
$subs = ['xy'];
Meaning that every x should be replaced by y in my string and every y should be replaced by x. Let's say that my substitution array can only contain pairs of characters to be replaced in my $string.
How would I go about doing this?
I tried using str_replace the following way but that doesn't work:
foreach ($subs as $sub) {
$sub_arr = str_split($sub);
$reversed_sub_arr = array_reverse($sub_arr);
$output = str_replace($sub_arr, $reversed_sub_arr, str_split($string));
}
$output = implode('', $output);
But the output gives me xxxxzz
The output should be yyxxzz
Thanks for any help

This working for your case
$string = 'xxyyzz';
$subs = ['xy'];
foreach ($subs as $sub) {
$sub_arr = str_split($sub);
$output = strtr($string, array($sub_arr[0]=>$sub_arr[1], $sub_arr[1]=>$sub_arr[0]));
}
echo $output; //yyxxzz

Extending #Orgil answer if two items in $subs array like $subs = ['xy', 'dz']
$string = $output = 'xxyyzz';
$subs = ['xy', 'dz'];
foreach ($subs as $sub) {
$sub_arr = str_split($sub);
$output = strtr($output, array($sub_arr[0]=>$sub_arr[1], $sub_arr[1]=>$sub_arr[0]));
}
echo $output;
Demo

Related

Automatically add links to strings of keywords

In my article, I want to automatically add links to keywords.
My keywords array:
$keywords = [
0=>['id'=>1,'slug'=>'getName','url'=>'https://example.com/1'],
1=>['id'=>2,'slug'=>'testName','url'=>'https://example.com/2'],
2=>['id'=>3,'slug'=>'ign','url'=>'https://example.com/3'],
];
This is my code:
private function keywords_replace(string $string, array $key_array)
{
$array_first = $key_array;
$array_last = [];
foreach ($array_first as $key=>$value)
{
$array_last[$key] = [$key, $value['slug'], '<a target="_blank" href="' . $value['url'] . '" title="' . $value['slug'] . '">' . $value['slug'] . '</a>'];
}
$count = count($array_last);
for ($i=0; $i<$count;$i++)
{
for ($j=$count-1;$j>$i;$j--)
{
if (strlen($array_last[$j][1]) > strlen($array_last[$j-1][1]))
{
$tmp = $array_last[$j];
$array_last[$j] = $array_last[$j-1];
$array_last[$j-1] = $tmp;
}
}
}
$keys = $array_last;
foreach ($keys as $key)
{
$string = str_ireplace($key[1],$key[0],$string);
}
foreach ($keys as $key)
{
$string = str_ireplace($key[0],$key[2],$string);
}
return $string;
}
result:
$str = "<p>Just a test: getName testName";
echo $this->keywords_replace($str,$keywords);
like this:Just a test: getName testName
very import: If the string has no spaces, it will not match.Because I will use other languages, sentences will not have spaces like English. Like Wordpress key words auto link
I think my code is not perfect,Is there a better algorithm to implement this function? Thanks!
You can use array_reduce and preg_replace to replace all occurrences of the slug words in your string with the corresponding url values:
$keywords = [
0=>['id'=>1,'slug'=>'getName','url'=>'https://www.getname.com'],
1=>['id'=>2,'slug'=>'testName','url'=>'https://www.testname.com'],
2=>['id'=>3,'slug'=>'ign','url'=>'https://www.ign.com'],
];
$str = "<p>Just a test: getName testName";
echo array_reduce($keywords, function ($c, $v) { return preg_replace('/\\b(' . $v['slug'] . ')\\b/', $v['url'], $c); }, $str);
Output:
<p>Just a test: https://www.getname.com https://www.testname.com
Demo on 3v4l.org
Update
To change the text into links, you need to use this:
echo array_reduce($keywords,
function ($c, $v) {
return preg_replace('/\\b(' . $v['slug'] . ')\\b/',
'$1', $c);
},
$str);
Output:
<p>Just a test: getName testName
Updated demo
Update 2
Because some of the links that are being substituted include words that are also values of slug, it's necessary to do all the replacements at once using the array format of strtr. We build an array of patterns and replacements using array_column, array_combine and array_map, then pass that to strtr:
$reps = array_combine(array_column($keywords, 'slug'),
array_map(function ($k) { return '' . $k['slug'] . ''; }, $keywords
));
$newstr = strtr($str, $reps);
New demo
First you need to change structure of array to key/value using loop that result stored in $newKeywords. Then using preg_replace_callback() select every word in string and check that it exist in key of array. If exist, wrap it in anchor tag.
$newKeywords = [];
foreach ($keywords as $keyword)
$newKeywords[$keyword['slug']] = $keyword['url'];
$newStr = preg_replace_callback("/(\w+)/", function($m) use($newKeywords){
return isset($newKeywords[$m[0]]) ? "<a href='{$newKeywords[$m[0]]}'>{$m[0]}</a>" : $m[0];
}, $str);
Output:
<p>Just a test: <a href='https://www.getname.com'>getName</a> <a href='https://www.testname.com'>testName</a></p>
Check result in demo
My answer uses preg_replace as does Nick's above.
It relies on the patterns and replacements being equally sized arrays, with corresponding patterns and replacements.
Word boundaries need to be respected, which I doubt you can do with a simple string replacement.
<?php
$keywords = [
0=>['id'=>1,'slug'=>'foo','url'=>'https://www.example.com/foo'],
1=>['id'=>2,'slug'=>'bar','url'=>'https://www.example.com/bar'],
2=>['id'=>3,'slug'=>'baz','url'=>'https://www.example.com/baz'],
];
foreach ($keywords as $item)
{
$patterns[] = '#\b(' . $item['slug'] . ')\b#i';
$replacements[] = '$1';
}
$html = "<p>I once knew a barbed man named <i>Foo</i>, he often visited the bar.</p>";
print preg_replace($patterns, $replacements, $html);
Output:
<p>I once knew a barbed man named <i>Foo</i>, he often visited the bar.</p>
This is my answer: thanks for #Nick
$content = array_reduce($keywords , function ($c, $v) {
return preg_replace('/(>[^<>]*?)(' . $v['slug'] . ')([^<>]*?<)/', '$1$2$3', $c);
}, $str);

Backreference preg_replace with commas in subject

Can you please help me find the preg_replace syntax so i can duplicate the price where it is missing?
The subject is:
...nomaterwhat13124123,"321,00",,nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00",,nomaterwhat
...nomaterwhat31313,"241,00",,nomaterwhat
My output want to be:
...nomaterwhat13124123,"321,00","321,00",nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00","211,00",nomaterwhat
...nomaterwhat31313,"241,00","241,00",nomaterwhat
I tried
preg_replace("(\W+),,nomaterwhat$", "$1,$1,nomaterwhat", $string);
Ignoring more complex cases this should do:
$result = preg_replace('/,"(\d+,\d{2})",,nomaterwhat/', ',"$1",$1,nomaterwhat', $string);
If you use str_getcsv you can do something like this:
$data = "CSV VALUES";
$lines = explode("\n", $data);
foreach ($lines as $line) {
$temp = str_getcsv($line);
echo '<pre>' . print_r($temp, true) . '</pre>';
}
Then you can put these into an array like so:
$data = "CSV VALUES";
$lines = explode("\n", $data);
$output = array();
foreach ($lines as $line) {
$temp = str_getcsv($line);
$temp[5] = ($temp[5] == '') ? $temp[4] : $temp[5];
$output[] = $temp;
}
echo '<pre>' . print_r($output, true) . '</pre>';
Replace $temp[5] with the place that the 2nd price should be.
You have a few issues with your regex.
1. No delimiter
2. No m modifier so $ is the end of the string, not line.
3. \W+ is a non a-z, 0-9, and/or _ so you wouldn't have gotten the
money value there anyway.
Try this out:
$string = '...nomaterwhat13124123,"321,00",,nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00",,nomaterwhat
...nomaterwhat31313,"241,00",,nomaterwhat';
echo preg_replace("/,(\"\d+,\d{2}\"),,nomaterwhat$/m", ",$1,$1,nomaterwhat", $string);
Output:
...nomaterwhat13124123,"321,00","321,00",nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00","211,00",nomaterwhat
...nomaterwhat31313,"241,00","241,00",nomaterwhat
Regex Demo: https://regex101.com/r/hE2zQ7/1
PHP Demo: http://ideone.com/OanPN1

How do I convert a PHP foreach output into a string?

function Foo($word) {
$lowerword= strtolower($word);
$words = explode(" ", $lowerword);
foreach ($words as $wrd){
echo $wrd[0];
}
}
$word = "my name is";
$firstletters = Foo($word);
Source code above. The idea is to take the first letter from each word in a sentence and piece them together as one string that can then be further manipulated. However, I am having difficulty manipulating the output, making me think that the output is not really one string. How do I convert the output of the foreach loop into a string?
The output is not a string at all indeed. Your function does echo but doesn't return anything.
Try this function:
function Foo($word) {
$lowerword= strtolower($word);
$words = explode(" ", $lowerword);
$firstLetters = '';
foreach ($words as $wrd){
$firstLetters .= $wrd[0];
}
return $firstLetters;
}

Extracting Twitter hashtag from string in PHP

I need some help with twitter hashtag, I need to extract a certain hashtag as string variable in PHP.
Until now I have this
$hash = preg_replace ("/#(\\w+)/", "#$1", $tweet_text);
but this just transforms hashtag_string into link
Use preg_match() to identify the hash and capture it to a variable, like so:
$string = 'Tweet #hashtag';
preg_match("/#(\\w+)/", $string, $matches);
$hash = $matches[1];
var_dump( $hash); // Outputs 'hashtag'
Demo
I think this function will help you:
echo get_hashtags($string);
function get_hashtags($string, $str = 1) {
preg_match_all('/#(\w+)/',$string,$matches);
$i = 0;
if ($str) {
foreach ($matches[1] as $match) {
$count = count($matches[1]);
$keywords .= "$match";
$i++;
if ($count > $i) $keywords .= ", ";
}
} else {
foreach ($matches[1] as $match) {
$keyword[] = $match;
}
$keywords = $keyword;
}
return $keywords;
}
As i understand you are saying that
in text/pargraph/post you want to show tag with hash sign(#) like this:- #tag
and in url you want to remove # sign because the string after # is not sended to server in request so i have edited your code and try out this:-
$string="www.funnenjoy.com is best #SocialNetworking #website";
$text=preg_replace('/#(\\w+)/','<a href=/hash/$1>$0</a>',$string);
echo $text; // output will be www.funnenjoy.com is best <a href=search/SocialNetworking>#SocialNetworking</a> <a href=/search/website>#website</a>
Extract multiple hashtag to array
$body = 'My #name is #Eminem, I am rap #god, #Yoyoya check it #out';
$hashtag_set = [];
$array = explode('#', $body);
foreach ($array as $key => $row) {
$hashtag = [];
if (!empty($row)) {
$hashtag = explode(' ', $row);
$hashtag_set[] = '#' . $hashtag[0];
}
}
print_r($hashtag_set);
You can use preg_match_all() PHP function
preg_match_all('/(?<!\w)#\w+/', $description, $allMatches);
will give you only hastag array
preg_match_all('/#(\w+)/', $description, $allMatches);
will give you hastag and without hastag array
print_r($allMatches)
You can extract a value in a string with preg_match function
preg_match("/#(\w+)/", $tweet_text, $matches);
$hash = $matches[1];
preg_match will store matching results in an array. You should take a look at the doc to see how to play with it.
Here's a non Regex way to do it:
<?php
$tweet = "Foo bar #hashTag hello world";
$hashPos = strpos($tweet,'#');
$hashTag = '';
while ($tweet[$hashPos] !== ' ') {
$hashTag .= $tweet[$hashPos++];
}
echo $hashTag;
Demo
Note: This will only pickup the first hashtag in the tweet.

Replace everything from beginning of line to equal sign

For a content with the format:
KEY=VALUE
like:
LISTEN=I am listening.
I need to do some replacing using regex. I want this regular expression to replace anything before the = with $key (making it have to be from beginning of line so a key like 'EN' wont replace a key like "TOKEN".
Here's what I'm using, but it doesn't seem to work:
$content = preg_replace('~^'.$key.'\s?=[^\n$]+~iu',$newKey,$content);
$content = "foo=one\n"
. "bar=two\n"
. "baz=three\n";
$keys = array(
'foo' => 'newFoo',
'bar' => 'newBar',
'baz' => 'newBaz',
);
foreach ( $keys as $oldKey => $newKey ) {
$oldKey = preg_quote($oldKey, '#');
$content = preg_replace("#^{$oldKey}( ?=)#m", "{$newKey}\\1", $content);
}
echo $content;
Output:
newFoo=one
newBar=two
newBaz=three
$str = 'LISTEN=I am listening.';
$new_key = 'ÉCOUTER';
echo preg_replace('/^[^=]*=/', $new_key . '=', $str);
If I understood your question well, you need to switch the multi-line mode on using m modifier.
$content = preg_replace('/^'.preg_quote($key, '/').'(?=\s?=)/ium', $newKey, $content);
By the way I do recommend to escape the $key using preg_quote to avoid unexpected results.
So if the source content is this:
KEY1=VALUE1
HELLO=WORLD
KEY3=VALUE3
The result will be this (if $key=HELLO and $newKey=BYE):
KEY1=VALUE1
BYE=WORLD
KEY3=VALUE3
This should do the trick.
\A is the start of a line, and the parentheses is for grouping things to keep/replace.
$new_content = preg_replace("/\A(.*)(=.*)/", "$key$2", $content);
$content = 'LISTEN=I am listening.';
$key = 'LISTEN';
$newKey = 'NEW';
$content = preg_replace('~^'.$key.'(\s?=)~iu',$newKey.'$1',$content);
echo $content;
output is NEW=I am listening.
But is does not change on a partial match
$content = 'LISTEN=I am listening.';
$key = 'TEN';
$new_key = 'NEW';
$content = preg_replace('~^'.$key.'(\s?=)~iu',$newKey.'$1',$content);
echo $content;
Output is LISTEN=I am listening.

Categories