replace everything except specific words in PHP - php

Is it possible to use php's preg_replace to remove anything in a string except specific words?
For example:
$text = 'Hello, this is a test string from php.';
I want to remove everything except "test" and "php" so it will be:
$text will be 'test php'

You could always use a callback. Under PHP 5.3:
$keep = array('test'=>1, 'php'=>1);
$text = trim(
preg_replace(
'/[^A-Za-z]+/', ' ',
preg_replace_callback(
'/[A-Za-z]+/',
function ($matched) use (&keep) {
if (isset($keep[$matched[0]])) {
return $matched[0];
}
return '';
}, $text
) ) );
Alternatively:
$text =
array_intersect(
preg_split('/[^A-Za-z]+/', $text),
array('test', 'php')
);

$text = 'Hello, this is a test string from php.';
$words = preg_split('~\W~', $text, -1, PREG_SPLIT_NO_EMPTY);
$allowed_words = array('test'=>1, 'php'=>1);
$output = array();
foreach($words as $word)
{
if(isset($allowed_words[$word]))
{
$output[] = $word;
}
}
print implode(' ', $output);

Related

remove - and make every letter after as capital in the string - PHP [duplicate]

I want to take a string like this: 'this-is-a-string' and convert it to this: 'thisIsAString':
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
// Do stuff
return $string;
}
I need to convert "kebab-case" to "camelCase".
No regex or callbacks necessary. Almost all the work can be done with ucwords:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
{
$str = str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));
if (!$capitalizeFirstCharacter) {
$str[0] = strtolower($str[0]);
}
return $str;
}
echo dashesToCamelCase('this-is-a-string');
If you're using PHP >= 5.3, you can use lcfirst instead of strtolower.
Update
A second parameter was added to ucwords in PHP 5.4.32/5.5.16 which means we don't need to first change the dashes to spaces (thanks to Lars Ebert and PeterM for pointing this out). Here is the updated code:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
{
$str = str_replace('-', '', ucwords($string, '-'));
if (!$capitalizeFirstCharacter) {
$str = lcfirst($str);
}
return $str;
}
echo dashesToCamelCase('this-is-a-string');
This can be done very simply, by using ucwords which accepts delimiter as param:
function camelize($input, $separator = '_')
{
return str_replace($separator, '', ucwords($input, $separator));
}
NOTE: Need php at least 5.4.32, 5.5.16
Overloaded one-liner, with doc block...
/**
* Convert underscore_strings to camelCase (medial capitals).
*
* #param {string} $str
*
* #return {string}
*/
function snakeToCamel ($str) {
// Remove underscores, capitalize words, squash, lowercase first.
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $str))));
}
In Laravel use Str::camel()
use Illuminate\Support\Str;
$converted = Str::camel('foo_bar');
// fooBar
this is my variation on how to deal with it. Here I have two functions, first one camelCase turns anything into a camelCase and it wont mess if variable already contains cameCase. Second uncamelCase turns camelCase into underscore (great feature when dealing with database keys).
function camelCase($str) {
$i = array("-","_");
$str = preg_replace('/([a-z])([A-Z])/', "\\1 \\2", $str);
$str = preg_replace('#[^a-zA-Z0-9\-_ ]+#', '', $str);
$str = str_replace($i, ' ', $str);
$str = str_replace(' ', '', ucwords(strtolower($str)));
$str = strtolower(substr($str,0,1)).substr($str,1);
return $str;
}
function uncamelCase($str) {
$str = preg_replace('/([a-z])([A-Z])/', "\\1_\\2", $str);
$str = strtolower($str);
return $str;
}
lets test both:
$camel = camelCase("James_LIKES-camelCase");
$uncamel = uncamelCase($camel);
echo $camel." ".$uncamel;
I would probably use preg_replace_callback(), like this:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
return preg_replace_callback("/-[a-zA-Z]/", 'removeDashAndCapitalize', $string);
}
function removeDashAndCapitalize($matches) {
return strtoupper($matches[0][1]);
}
You're looking for preg_replace_callback, you can use it like this :
$camelCase = preg_replace_callback('/-(.?)/', function($matches) {
return ucfirst($matches[1]);
}, $dashes);
here is very very easy solution in one line code
$string='this-is-a-string' ;
echo str_replace('-', '', ucwords($string, "-"));
output ThisIsAString
Try this:
$var='snake_case';
$ucword= ucword($var,'_');
echo $ucword;
Output:
Snake_Case
remove _ with str_replace
str_replace('_','',$ucword); //SnakeCase
and result
$result='SnakeCase'; //pascal case
echo lcfirst('SnakeCase'); //snakeCase (camel case)
the important thing is the approach here I used snake case and camel case in the example
$string = explode( "-", $string );
$first = true;
foreach( $string as &$v ) {
if( $first ) {
$first = false;
continue;
}
$v = ucfirst( $v );
}
return implode( "", $string );
Untested code. Check the PHP docs for the functions im-/explode and ucfirst.
One liner, PHP >= 5.3:
$camelCase = lcfirst(join(array_map('ucfirst', explode('-', $url))));
The TurboCommons library contains a general purpose formatCase() method inside the StringUtils class, which lets you convert a string to lots of common case formats, like CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case, and many more.
https://github.com/edertone/TurboCommons
To use it, import the phar file to your project and:
use org\turbocommons\src\main\php\utils\StringUtils;
echo StringUtils::formatCase('sNake_Case', StringUtils::FORMAT_CAMEL_CASE);
// will output 'sNakeCase'
Here's the link to the method source code:
https://github.com/edertone/TurboCommons/blob/b2e015cf89c8dbe372a5f5515e7d9763f45eba76/TurboCommons-Php/src/main/php/utils/StringUtils.php#L653
function camelize($input, $separator = '_')
{
return lcfirst(str_replace($separator, '', ucwords($input, $separator)));
}
echo ($this->camelize('someWeir-d-string'));
// output: 'someWeirdString';
Try this ;)
$string = 'this-is-a-string';
$separator = '-';
$stringCamelize = str_replace(
$separator,
'',
lcfirst(
ucwords(
strtolower($string),
$separator
)
)
);
var_dump($stringCamelize); // -> 'thisIsAString'
Alternatively, if you prefer not to deal with regex, and want to avoid explicit loops:
// $key = 'some-text', after transformation someText
$key = lcfirst(implode('', array_map(function ($key) {
return ucfirst($key);
}, explode('-', $key))));
Another simple approach:
$nasty = [' ', '-', '"', "'"]; // array of nasty characted to be removed
$cameled = lcfirst(str_replace($nasty, '', ucwords($string)));
Many good solutions above, and I can provide a different way that no one mention before. This example uses array. I use this method on my project Shieldon Firewall.
/**
* Covert string with dashes into camel-case string.
*
* #param string $string A string with dashes.
*
* #return string
*/
function getCamelCase(string $string = '')
{
$str = explode('-', $string);
$str = implode('', array_map(function($word) {
return ucwords($word);
}, $str));
return $str;
}
Test it:
echo getCamelCase('This-is-example');
Result:
ThisIsExample
Some very good solutions here. I compiled them together for easy c&p
declare(strict_types=1);
/**
* convert kebab-case to PascalCase
*/
function kebabToPascal( string $str ): string {
return str_replace( ' ', '', ucwords( str_replace( '-', ' ', $str ) ) );
}
/**
* convert snake_case to PascalCase
*/
function snakeToPascal( string $str ): string {
return str_replace (' ', '', ucwords( str_replace( '_', ' ', $str ) ) );
}
/**
* convert snake_case to camelCase
*/
function snakeToCamel( string $str ): string {
return lcfirst( snakeToPascal( $str ) );
}
/**
* convert kebab-case to camelCase
*/
function kebabToCamel( string $str): string {
return lcfirst( kebabToPascal( $str ) );
}
echo snakeToCamel( 'snake_case' ). '<br>';
echo kebabToCamel( 'kebab-case' ). '<br>';
echo snakeToPascal( 'snake_case' ). '<br>';
echo kebabToPascal( 'kebab-case' ). '<br>';
echo kebabToPascal( 'It will BREAK on things-like_this' ). '<br>';
In Yii2 you can use yii\helpers\Inflector::camelize():
use yii\helpers\Inflector;
echo Inflector::camelize("send_email");
// outputs: SendEmail
Yii provides a lot of similar functions, see the Yii2 Docs.
function camelCase($text) {
return array_reduce(
explode('-', strtolower($text)),
function ($carry, $value) {
$carry .= ucfirst($value);
return $carry;
},
'');
}
Obviously, if another delimiter than '-', e.g. '_', is to be matched too, then this won't work, then a preg_replace could convert all (consecutive) delimiters to '-' in $text first...
If you use Laravel framework, you can use just camel_case() method.
camel_case('this-is-a-string') // 'thisIsAString'
Here is another option:
private function camelcase($input, $separator = '-')
{
$array = explode($separator, $input);
$parts = array_map('ucwords', $array);
return implode('', $parts);
}
$stringWithDash = 'Pending-Seller-Confirmation';
$camelize = str_replace('-', '', ucwords($stringWithDash, '-'));
echo $camelize;
output: PendingSellerConfirmation
ucwords second(optional) parameter helps in identify a separator to camelize the string.
str_replace is used to finalize the output by removing the separator.
Here is a small helper function using a functional array_reduce approach.
Requires at least PHP 7.0
private function toCamelCase(string $stringToTransform, string $delimiter = '_'): string
{
return array_reduce(
explode($delimiter, $stringToTransform),
function ($carry, string $part): string {
return $carry === null ? $part: $carry . ucfirst($part);
}
);
}
private function dashesToCamelCase($string)
{
$explode = explode('-', $string);
$return = '';
foreach ($explode as $item) $return .= ucfirst($item);
return lcfirst($return);
}
This works for me:
function camelCase($string){
$chunks = preg_split("/\s+|-|_/",$string);
$camel = "";
foreach ($chunks as $idx => $chunk){
if ($idx===0){
$camel = strtolower($chunk);
}else{
$camel .= ucfirst($chunk);
}
}
return $camel;
}
The shortest and most elegant solution would be:
function dashesToCamelCase($string, $capitalizeFirstCharacter = false) {
$result = join("", array_map("ucfirst", explode("-", $string)));
if ($capitalizeFirstCharacter === false) {
return lcfirst($result);
}
return $result;
}
One Line Option
echo str_replace(' ', '', lcfirst(ucwords(str_replace("_", " ", 'facebook_catalog_id_type'))));
//output: facebookCatalogIdType
Try this:
return preg_replace("/\-(.)/e", "strtoupper('\\1')", $string);
This is simpler :
$string = preg_replace( '/-(.?)/e',"strtoupper('$1')", strtolower( $string ) );

Jooml : preg_replace is deprecated

I am modifying one of our Joomla template and I am getting this warning.
Deprecated: preg_replace(): The /e modifier is deprecated, use
preg_replace_callback instead in
/home/folder/public_html/components/com_joomgallery/helpers/helper.php
on line 255
Code is like this :
$text = preg_replace('/('.$replace2.')/ie', $replace, $text);
Entire code block :
public static function createPagetitle($text, $catname = '', $imgtitle = '', $page_title = '')
{
preg_match_all('/(\[\!.*?\!\])/i', $text, $results);
define('COM_JOOMGALLERY_COMMON_CATEGORY', JText::_('COM_JOOMGALLERY_COMMON_CATEGORY'));
define('COM_JOOMGALLERY_COMMON_IMAGE', JText::_('COM_JOOMGALLERY_COMMON_IMAGE'));
for($i = 0; $i<count($results[0]); $i++)
{
$replace = str_replace('[!', '', $results[0][$i]);
$replace = str_replace('!]', '', $replace);
$replace = trim($replace);
$replace2 = str_replace('[!', '\[\!', $results[0][$i]);
$replace2 = str_replace('!]', '\!\]', $replace2);
$text = preg_replace('/('.$replace2.')/ie', $replace, $text);
}
$text = str_replace('#cat', $catname, $text);
$text = str_replace('#img', $imgtitle, $text);
$text = str_replace('#page_title', $page_title, $text);
$text = self::addSitenameToPagetitle($text);
return $text;
}
Finally, this code worked :
$text = preg_replace_callback('/('.$replace2.')/',create_function('$replace','return #replace;'),$text);
Thank you all.

PHP: How to find text NOT between particular tags?

Example input string: "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3"
I need to find out what parts of text are NOT between the A, B and C tags. So, for example, in the above string it's 'test2' and 'test3'. 'test2' doesn't have the C tag and 'test3' doesn't have any tag at all.
If can also be nested like this:
Example input string2: "[A][B][C]test1[/B][/C][/A] [A][B]test2[C]test4[/C][/B][/A] test3"
In this example "test4" was added but "test4" has the A,B and C tag so the output wouldn't change.
Anyone got an idea how I could parse this?
This solution is not clean but it does the trick
$string = "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3" ;
$string = preg_replace('/<A[^>]*>([\s\S]*?)<\/A[^>]*>/', '', strtr($string, array("["=>"<","]"=>">")));
$string = trim($string);
var_dump($string);
Output
string 'test3' (length=5)
Considering the fact that everyone of you tags is in [A][/A] What you can do is: Explode the [/A] and verify if each array contains the [A] tag like so:
$string = "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3";
$found = ''; // this will be equal to test3
$boom = explode('[/A]', $string);
foreach ($boom as $val) {
if (strpos($val, '[A] ') !== false) { $found = $val; break; }
}
echo $found; // test3
try the below code
$str = 'test0[A]test1[B][C]test2[/B][/C][/A] [A][B]test3[/B][/A] test4';
$matches = array();
// Find and remove the unneeded strings
$pattern = '/(\[A\]|\[B\]|\[C\])[^\[]*(\[A\]|\[B\]|\[C\])[^\[]*(\[A\]|\[B\]|\[C\])([^\[]*)(\[\/A\]|\[\/B\]|\[\/C\])[^\[]*(\[\/A\]|\[\/B\]|\[\/C\])[^\[]*(\[\/A\]|\[\/B\]|\[\/C\])/';
preg_match_all( $pattern, $str, $matches );
$stripped_str = $str;
foreach ($matches[0] as $key=>$matched_pattern) {
$matched_pattern_str = str_replace($matches[4][$key], '', $matched_pattern); // matched pattern with text between A,B,C tags removed
$stripped_str = str_replace($matched_pattern, $matched_pattern_str, $stripped_str); // replace pattern string in text with stripped pattern string
}
// Get required strings
$pattern = '/(\[A\]|\[B\]|\[C\]|\[\/A\]|\[\/B\]|\[\/C\])([^\[]+)(\[A\]|\[B\]|\[C\]|\[\/A\]|\[\/B\]|\[\/C\])/';
preg_match_all( $pattern, $stripped_str, $matches );
$required_strings = array();
foreach ($matches[2] as $match) {
if (trim($match) != '') {
$required_strings[] = $match;
}
}
// Special case, possible string on start and end
$pattern = '/^([^\[]*)(\[A\]|\[B\]|\[C\]).*(\[\/A\]|\[\/B\]|\[\/C\])([^\[]*)$/';
preg_match( $pattern, $stripped_str, $matches );
if (trim($matches[1]) != '') {
$required_strings[] = $matches[1];
}
if (trim($matches[4]) != '') {
$required_strings[] = $matches[4];
}
print_r($required_strings);

how to do a preg_replace on a string in php?

i have some simple code that does a preg match:
$bad_words = array('dic', 'tit', 'fuc',); //for this example i replaced the bad words
for($i = 0; $i < sizeof($bad_words); $i++)
{
if(preg_match("/$bad_words[$i]/", $str, $matches))
{
$rep = str_pad('', strlen($bad_words[$i]), '*');
$str = str_replace($bad_words[$i], $rep, $str);
}
}
echo $str;
So, if $str was "dic" the result will be '*' and so on.
Now there is a small problem if $str == f.u.c. The solution might be to use:
$pattern = '~f(.*)u(.*)c(.*)~i';
$replacement = '***';
$foo = preg_replace($pattern, $replacement, $str);
In this case i will get ***, in any case. My issue is putting all this code together.
I've tried:
$pattern = '~f(.*)u(.*)c(.*)~i';
$replacement = 'fuc';
$fuc = preg_replace($pattern, $replacement, $str);
$bad_words = array('dic', 'tit', $fuc,);
for($i = 0; $i < sizeof($bad_words); $i++)
{
if(preg_match("/$bad_words[$i]/", $str, $matches))
{
$rep = str_pad('', strlen($bad_words[$i]), '*');
$str = str_replace($bad_words[$i], $rep, $str);
}
}
echo $str;
The idea is that $fuc becomes fuc then I place it in the array then the array does its jobs, but this doesn't seem to work.
First of all, you can do all of the bad word replacements with one (dynamically generated) regex, like this:
$bad_words = array('dic', 'tit', 'fuc',);
$str = preg_replace_callback("/\b(?:" . implode( '|', $bad_words) . ")\b/",
function( $match) {
return str_repeat( '*', strlen( $match[0]));
}, $str);
Now, you have the problem of people adding periods in between the word, which you can search for with another regex and replace them as well. However, you must keep in mind that . matches any character in a regex, and must be escaped (with preg_quote() or a backslash).
$bad_words = array_map( function( $el) {
return implode( '\.', str_split( $el));
}, $bad_words);
This will create a $bad_words array similar to:
array(
'd\.i\.c',
't\.i\.t',
'f\.u\.c'
)
Now, you can use this new $bad_words array just like the above one to replace these obfuscated ones.
Hint: You can make this array_map() call "better" in the sense that it can be smarter to catch more obfuscations. For example, if you wanted to catch a bad word separated with either a period or a whitespace character or a comma, you can do:
$bad_words = array_map( function( $el) {
return implode( '(?:\.|\s|,)', str_split( $el));
}, $bad_words);
Now if you make that obfuscation group optional, you'll catch a lot more bad words:
$bad_words = array_map( function( $el) {
return implode( '(?:\.|\s|,)?', str_split( $el));
}, $bad_words);
Now, bad words should match:
f.u.c
f,u.c
f u c
fu c
f.uc
And many more.

Check if any array values are present at the end of a string

I am trying to test if a string made up of multiple words and has any values from an array at the end of it. The following is what I have so far. I am stuck on how to check if the string is longer than the array value being tested and that it is present at the end of the string.
$words = trim(preg_replace('/\s+/',' ', $string));
$words = explode(' ', $words);
$words = count($words);
if ($words > 2) {
// Check if $string ends with any of the following
$test_array = array();
$test_array[0] = 'Wizard';
$test_array[1] = 'Wizard?';
$test_array[2] = '/Wizard';
$test_array[4] = '/Wizard?';
// Stuck here
if ($string is longer than $test_array and $test_array is found at the end of the string) {
Do stuff;
}
}
By end of string do you mean the very last word? You could use preg_match
preg_match('~/?Wizard\??$~', $string, $matches);
echo "<pre>".print_r($matches, true)."</pre>";
I think you want something like this:
if (preg_match('/\/?Wizard\??$/', $string)) { // ...
If it has to be an arbitrary array (and not the one containing the 'wizard' strings you provided in your question), you could construct the regex dynamically:
$words = array('wizard', 'test');
foreach ($words as &$word) {
$word = preg_quote($word, '/');
}
$regex = '/(' . implode('|', $words) . ')$/';
if (preg_match($regex, $string)) { // ends with 'wizard' or 'test'
Is this what you want (no guarantee for correctness, couldn't test)?
foreach( $test_array as $testString ) {
$searchLength = strlen( $testString );
$sourceLength = strlen( $string );
if( $sourceLength <= $searchLength && substr( $string, $sourceLength - $searchLength ) == $testString ) {
// ...
}
}
I wonder if some regular expression wouldn't make more sense here.

Categories