php preg_grep and umlaut/accent - php

I have an array that consists of terms, some of them contain accented characters. I do a preg grep like this
$data= array('Napoléon','Café');
$result = preg_grep('~' . $input . '~i', $data);
So if user type in 'le' I would also want the result 'Napoléon' to be matched, which does not work with the ablove command.
I did some searching and found that this function might be relevant
preg_match("/[\w\pL]/u",$var);
How can I combine these and make it work?

This is not possible with a regular expression pattern only. It is not because you can not tell the regex engine to match all "e" and similars. However, it is possible to first normalize the input data (both the array as well as the search input) and then search the normalized data but return the results for the non-normalized data.
In the following example I use transliteration to do this kind of normalization, I guess that is what you're looking for:
$data = ['Napoléon', 'Café'];
$result = array_translit_search('le', $data);
print_r($result);
$result = array_translit_search('leó', $data);
print_r($result);
The exemplary output is:
Array
(
[0] => Napoléon
)
Array
(
[0] => Napoléon
)
The search function itself is rather straight forward as written above, transliterating the inputs, doing the preg_grep and then returning the original intputs matches:
/**
* #param string $search
* #param array $data
* #return array
*/
function array_translit_search($search, array $data) {
$transliterator = Transliterator::create('ASCII-Latin', Transliterator::REVERSE);
$normalize = function ($string) use ($transliterator) {
return $transliterator->transliterate($string);
};
$dataTrans = array_map($normalize, $data);
$searchTrans = $normalize($search);
$pattern = sprintf('/%s/i', preg_quote($searchTrans));
$result = preg_grep($pattern, $dataTrans);
return array_intersect_key($data, $result);
}
This code requires the Transliterator from the Intl extension, you can replace it with any other similar transliteration or translation function.
I can not suggest to use str_replace here btw., if you need to fall-back to a translation table, use strtr instead. That is what you're looking for. But I prefer a library that brings the translation with it's own, especially if it's the Intl lib, you normally can't beat it.

You can write something like this:
$data = array('Napoléon','Café');
// do something with your input, but for testing purposes it will be simply as you wrote in your example
$input = 'le';
foreach($data as $var) {
if (preg_match("/".str_replace(array("é"....), array("e"....), $input)."/i", str_replace(array("é"....), array("e"....), $var)))
//do something as there is a match
}
Actually you even don't need regex in this case, simple strpos will be enough.

Related

php dynamic replacement with a std object

How can I make a dynamic replacement with a std object?
I can't get how to use $1 in this case :(
See below.
$lang->custom_name = "Me";
$lang->custom_email = "Me#me";
$html = "hello {{custom_name}} with {{custom_email}} ";
$html = preg_replace("/{{(custom_.*)}}/", $lang->{'$1'} , $html);
Instead of using preg_replace, use preg_replace_callback as it'll make it possible to use any mechanism you want to supply a replacement value.
// create stdClass
$obj = (object) ['custom_foo' => 'foo-repl', 'custom_bar' => 'bar-repl'];
$html = "{{custom_foo}} {{custom_bar}}";
$res = preg_replace_callback("#{{(custom_.*?)}}#", function ($m) use ($obj) {
// m (match) contains the complete match in [0] and the sub pattern in [1].
return $obj->{$m[1]};
}, $html);
var_dump($res); // string(17) "foo-repl bar-repl"
If you want to use this for handling localization values, there are other, always made libraries that handle both the definition files, translate tools, etc. Look into gettext and friends (and there are probably other modern alternatives in other frameworks).

Get the most letters in a string PHP

I Need PHP Function that can get the most letters from the string
$string = "111010111010001101";
$execute = SomeFunction($string);
echo $execute;
and the ouput will be like this
1
is there a php function like that? Thank you
Here you go
$string = "111010111010001101";
//$string = "abaacabdeeeee";
$array_count = array_count_values(str_split($string));
$res = array_keys($array_count, max($array_count));
print_r($res);
To make it a function, just do this:
function SomeFunction($string){
$array_count = array_count_values(str_split($string));
return array_keys($array_count, max($array_count));
}
print_r(SomeFunction('111010111010001101'));
Output
1 //or e in the commented one I tested
Sandbox
How it works:
Split the string into an array of chars str_split
count the occurrences of the chars array_count_values
get the key with the max number of occurrences array_keys and max
Caveats:
If two values are equal then they will both be returned in the result. For example
$string = 'ababababcd';
Output
Array
(
[0] => a
[1] => b
)
You never mentioned what you want to happen in this case (a tie). For your particular case that may not even be an issue. But I had to mention it for the sake of completeness. If you don't want the return as an array you can do something like this (to return false or the first element):
function SomeFunction($string){
$array_count = array_count_values(str_split($string));
$res = array_keys($array_count, max($array_count));
if(empty($res)) return false;
return array_shift($res);
}
Cheers!
Not effective but simple
max(str_split($string));
Yes, so long as your character set isn't a multibyte one with multibyte characters in the string. See the manual page for count_chars

PHP str_replace with function

Is it possible use str_replace() and use function in replace?
$value = "gal($data)";
$replace = str_replace($dat, $value, $string);
gal($data) is a function and I need replace one code for this function and show, but the script only give me finally this gal($data), and the function no show nothing
Is it possible use str_replace() for replace code and replace by the function or some similar method?
PHP has a function called preg_replace_callback that does this. When you pass it a callback function, it will pass each match through your function. You can choose to replace, based upon the matched value, or ignore it.
As an example, suppose I have a pattern that matches various strings, such as [a-z]+. I may not want to replace every instance with the same value, so I can call a function upon eat match found, and determine how I ought to respond:
function callback ($match) {
if ($match[0] === "Jonathan")
return "Superman";
return $match[0];
}
$subject = "This is about Jonathan.";
$pattern = "/[a-z]+/i";
$results = preg_replace_callback($pattern, "callback", $subject);
// This is about Superman.
echo $results;
Note in our callback function how I am able to return special values for certain matches, and not all matches.
Expanding Abbreviations
Another example would be a lookup. Suppose we wanted to find abbreviations of programming languages, and replace them with their full titles. We may have an array that has abbreviations as keys, with long-names as values. We could then use our callback ability to lookup the full-length names:
function lookup ($match) {
$langs = Array(
"JS" => "JavaScript",
"CSS" => "Cascading Style Sheets",
"JSP" => "Java Server Pages"
);
return $langs[$match[0]] ?: $match[0];
}
$subject = "Does anybody know JS? Or CSS maybe? What about PHP?";
$pattern = "/(js|css|jsp)/i";
$results = preg_replace_callback($pattern, "lookup", $subject);
// Does anybody know JavaScript? Or Cascading Style Sheets maybe? What about PHP?
echo $results;
So every time our regular expression finds a match, it passes the match through lookup, and we can return the appropriate value, or the original value.

stristr Case-insensitive search PHP

Please excuse my noob-iness!
I have a $string, and would like to see if it contains any one or more of a group of words, words link ct, fu, sl** ETC. So I was thinking I could do:
if(stristr("$input", "dirtyword1"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord");
}
elseif(stristr("$input", "dirtyWord1"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord2");
}
...ETC. BUT, I don't want to have to keep doing if/elseif/elseif/elseif/elseif...
Can't I just do a switch statement OR have an array, and then simply say something like?:
$dirtywords = { "f***", "c***", w****", "bit**" };
if(stristr("$input", "$dirtywords"))
{
$input = str_ireplace("$input", "thisWillReplaceDirtyWord");
}
I'd appreciate any help at all
Thank you
$dirty = array("fuc...", "pis..", "suc..");
$censored = array("f***", "p***", "s***");
$input= str_ireplace($dirty, $censored , $input);
Note, that you don't have to check stristr() to do a str_ireplace()
http://php.net/manual/en/function.str-ireplace.php
If search and replace are arrays, then str_ireplace() takes a value from each array and uses them to do search and replace on subject. If replace has fewer values than search, then an empty string is used for the rest of replacement values. If search is an array and replace is a string, then this replacement string is used for every value of search.
Surely not the best solution since I don't know too much PHP, but what about a loop ?
foreach (array("word1", "word2") as $word)
{
if(stristr("$input", $word))
{
$input = str_ireplace("$input", $word" "thisWillReplaceDirtyWord");
}
}
When you have several objects to test, think "loop" ;-)

Parse multiple predictably formatted substrings of user data existing in a single string

I have a really long string in a certain pattern such as:
userAccountName: abc userCompany: xyz userEmail: a#xyz.com userAddress1: userAddress2: userAddress3: userTown: ...
and so on. This pattern repeats.
I need to find a way to process this string so that I have the values of userAccountName:, userCompany:, etc. (i.e. preferably in an associative array or some such convenient format).
Is there an easy way to do this or will I have to write my own logic to split this string up into different parts?
Simple regular expressions like this userAccountName:\s*(\w+)\s+ can be used to capture matches and then use the captured matches to create a data structure.
If you can arrange for the data to be formatted as it is in a URL (ie, var=data&var2=data2) then you could use parse_str, which does almost exactly what you want, I think. Some mangling of your input data would do this in a straightforward manner.
You might have to use regex or your own logic.
Are you guaranteed that the string ": " does not appear anywhere within the values themselves? If so, you possibly could use implode to split the string into an array of alternating keys and values. You'd then have to walk through this array and format it the way you want. Here's a rough (probably inefficient) example I threw together quickly:
<?php
$keysAndValuesArray = implode(': ', $dataString);
$firstKeyName = 'userAccountName';
$associativeDataArray = array();
$currentIndex = -1;
$numItems = count($keysAndValuesArray);
for($i=0;$i<$numItems;i+=2) {
if($keysAndValuesArray[$i] == $firstKeyName) {
$associativeDataArray[] = array();
++$currentIndex;
}
$associativeDataArray[$currentIndex][$keysAndValuesArray[$i]] = $keysAndValuesArray[$i+1];
}
var_dump($associativeDataArray);
If you can write a regexp (for my example I'm considering there're no semicolons in values), you can parse it with preg_split or preg_match_all like this:
<?php
$raw_data = "userAccountName: abc userCompany: xyz";
$raw_data .= " userEmail: a#xyz.com userAddress1: userAddress2: ";
$data = array();
// /([^:]*\s+)?/ part works because the regexp is "greedy"
if (preg_match_all('/([a-z0-9_]+):\s+([^:]*\s+)?/i', $raw_data,
$items, PREG_SET_ORDER)) {
foreach ($items as $item) {
$data[$item[1]] = $item[2];
}
print_r($data);
}
?>
If that's not the case, please describe the grammar of your string in a bit more detail.
PCRE is included in PHP and can respond to your needs using regexp like:
if ($c=preg_match_all ("/userAccountName: (<userAccountName>\w+) userCompany: (<userCompany>\w+) userEmail: /", $txt, $matches))
{
$userAccountName = $matches['userAccountName'];
$userCompany = $matches['userCompany'];
// and so on...
}
the most difficult is to get the good regexp for your needs.
you can have a look at http://txt2re.com for some help
I think the solution closest to what I was looking for, I found at http://www.justin-cook.com/wp/2006/03/31/php-parse-a-string-between-two-strings/. I hope this proves useful to someone else. Thanks everyone for all the suggested solutions.
If i were you, i'll try to convert the strings in a json format with some regexp.
Then, simply use Json.

Categories