Replace everything from beginning of line to equal sign - php

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.

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

remove subdomain from url PHP

I'm cleaning URL from a text file with a PHP script, here's the code right now :
$file = __DIR__."/url.txt";
$f = fopen($file, "r");
$array1 = array();
while ( $line = fgets($f, 1000) ) {
$nl = mb_strtolower($line,'UTF-8');
$array1[] = $nl;
}
foreach ($array1 as $value) {
$value = preg_replace('#^https?://#', '', $value);
$value = preg_replace('#^www.#', '', $value);
echo $value."<br>";
}
So I remove the http:// and www from these urls
Here's the output :
urlnumberone.com
urlnumbertwo.uk
subdomain.urlnumberthree.com
urlnumberfour.com
What I want is to remove subdomain too, and just have urlnumberthree.com
Thanks for your help !
Pure regex solution:
preg_match('#[^\.]+[\.]{1}[^\.]+$#', $value , $matches);
$value = $matches[0];
This replaces both of your preg_replaces.
Check occurrences of '.' if they are more than 1, remove the beginning until first dot.

Extract everything within brackets

I have a string of HTML with tags inside saved in the database e.g:
<p>Hello {$name}, welcome to {$shop_name}....</p>
I want to replace all of the tags with real data, now at the moment I loop through all available data and replace if it exists.
foreach($data as $key => $data){
$content = str_replace('{$'.$key.'}', $data, $content);
}
Is there a better way of doing this without looping through all of the $data? This is now growing to over 5000 rows.
I mean is it possible to extract all variables {$name}/{$shop_name} then do a replace on only the found?
You can do it with a single str_replace call.
$find = array();
$replace = array();
foreach($data as $key => $data) {
$find[] = "\{$" . $key . "}";
$replace[] = $data;
}
$content = str_replace($find, $replace, $content);
Unless there is a real performance issue, I wouldn't worry about it too much.
str_replace accepts arrays, you can build the array with array_keys, array_values and user array_map to add the {$}
$content = str_replace(
array_map(function($e) { return '{$' . $e . '}';}, array_keys($data)),
array_values($data),
$content);
Can just do
$content = preg_replace('/\{$(\w+)\}/e', '$data[\'$1\']', $content);

str_replace doesn't work with foreach

My code:
$str = array(
'{$string1}' => 'anything2',
'{$string2}' => 'something1',
'{$string3}' => '...'
);
$final = "";
$text = $_POST['content'];
foreach( $str as $key => $val ) {
$final = str_replace($key, $val, $text);
}
My $text ofc. has {string1} , {string2} and {string3} itself, but it doesn't replace it with the values given in the array.
Why its not working?
This code does exactly what you need (without any extra loops):
$final = strtr($_POST['content'], $str);
use
$final = str_replace('{'.$key.'}', $val, $text);
Ref : http://php.net/manual/en/function.str-replace.php
Maybe the different enconding, try this:
$text = utf8_decode($_POST['content']);// or utf8_encode
before loop;
Good lucky!

Could you tell how to replace by regular expression

Could you tell how to replace string by preg-replace (need regular expression):
/user/{parent_id}/{action}/step/1
At the equivalent values of an array:
array('parent_id'=>32, 'action'=>'some');
To make:
/user/32/some/step/1
Addition
This is a typical problem, so I probably will not know what the names of variables come
You can use str_replace
For example:
str_replace(array("{parent_id}", "{action}"), array(32, 'some'), "/user/{parent_id}/{action}/step/1");
$arr = array('parent_id'=>32, 'action'=>'some');
$out = str_replace(array_keys($arr),array_values($arr),$in);
no need for regexps!
Say you have:
$arr = array('parent_id'=>32, 'action'=>'some');
$in = '/usr/{parent_id}/{action}/step/1';
This will replace the braces:
function bracelize($str) {
return '{' . $str . '}';
}
$search = array_map('bracelize', array_keys($arr));
$out = str_replace($search, $arr, $in);
Or if you are using PHP >= 5.3 you can use lambdas:
$search = array_map(function ($v) { return '{'.$v.'}';}, array_keys($arr));
$out = str_replace($search, $arr, $in);
$s = '/user/{parent_id}/{action}/step/1';
$replacement = array('parent_id'=>32, 'action'=>'some');
$res = preg_replace(array('/\\{parent_id\\}/', '/\\{action\\}/'), $replacement, $s);
Of course, you could just as well use str_replace (in fact, you ought to).
<?php
$string = '/usr/{parent_id}/{action}/step/1';
$pattern = array('#{parent_id}#', '#{action}#');
$values = array('32', 'some');
echo preg_replace($pattern, $values, $string);
?>
If your problem is not more complicated than this, i would recommend changing preg_replace to str_replace though.
EDIT: I see you don't know the variable names in advance. In which case you could do something like this.
<?php
function wrap_in_brackets(&$item)
{
$item = '{' . $item . '}';
return true;
}
$string = '/usr/{parent_id}/{action}/step/1';
$variables = array('parent_id' => 32, 'action' => 'some');
$keys = array_keys($variables);
array_walk($keys, 'wrap_in_brackets');
echo str_replace($keys, array_values($variables), $string);
?>
Expanding on mvds' answer:
$in = 'user/{parent_id}/{action}/step/1';
$arr = array('{parent_id}' => 32, '{action}' => 'some');
$out = str_replace(array_keys($arr), $arr, $in);
Or:
$in = 'user/{parent_id}/{action}/step/1';
$arr = array('parent_id' => 32, 'action' => 'some');
$arr[] = '';
$find = array_merge(array_keys($arr), array('{', '}'));
$out = str_replace($find, $arr, $in);

Categories