How can I use the PHP strtoupper function for the first two characters of a string? Or is there another function for that?
So the string 'hello' or 'Hello' must be converted to 'HEllo'.
$txt = strtoupper( substr( $txt, 0, 2 ) ).substr( $txt, 2 );
This works also for strings that are less than 2 characters long.
$string = "hello";
$string{0} = strtoupper($string{0});
$string{1} = strtoupper($string{1});
var_dump($string);
//output: string(5) "HEllo"
Assuming it's just a single word you need to do:
$ucfirsttwo = strtoupper(substr($word, 0, 2)) . substr($word, 2);
Basically, extract the first two characters and uppercase the, then attach the remaining characters.
If you need to handle multiple words in the string, then it gets a bit uglier.
Oh, and if you're using multi-byte characters, prefix the two functions with mb_ to get a multibyte-aware version.
$str = substr_replace($str, strtoupper($str[0].$str[1]), 1, 2);
Using preg_replace() with the e pattern modifier could be interesting here:
$str = 'HELLO';
echo preg_replace('/^(\w{1,2})/e', 'strtoupper(\\1)', strtolower($str));
EDIT: It is recommended that you not use this approach. From the PHP manual:
Use of this modifier is discouraged, as it can easily introduce security vulnerabilites:
<?php
$html = $_POST['html'];
// uppercase headings
$html = preg_replace(
'(<h([1-6])>(.*?)</h\1>)e',
'"<h$1>" . strtoupper("$2") . "</h$1>"',
$html
);
The above example code can be easily exploited by passing in a string
such as <h1>{${eval($_GET[php_code])}}</h1>. This gives the attacker
the ability to execute arbitrary PHP code and as such gives him nearly
complete access to your server.
To prevent this kind of remote code execution vulnerability the
preg_replace_callback() function should be used instead:
<?php
$html = $_POST['html'];
// uppercase headings
$html = preg_replace_callback(
'(<h([1-6])>(.*?)</h\1>)',
function ($m) {
return "<h$m[1]>" . strtoupper($m[2]) . "</h$m[1]>";
},
$html
);
As recommended, instead of using the e pattern, consider using preg_replace_callback():
$str = 'HELLO';
echo preg_replace_callback(
'/^(\w{1,2})/'
, function( $m )
{
return strtoupper($m[1]);
}
, strtolower($str)
);
This should work strtoupper(substr($target, 0, 2)) . substr($target, 2) where $target is your 'hello' or whatever.
ucfirstDocs does only the first, but substr access on strings works, too:
$str = ucfirst($str);
$str[1] = strtoupper($str[1]);
Remark: This works, but you will get notices on smaller strings if offset 1 is not defined, so not that safe, empty strings will even be converted to array. So it's merely to show some options.
Related
I want to find a number in a string, add one to it, and replace it. These don't work:
$new_version =
preg_replace("/str\/(\d+)str/", "str/".("$1"+1)."str", $original);
$new_version =
preg_replace("/str\/(\d+)str/", "str/".(intval("$1")+1)."str", $original);
Where 'str' is a very identifiable string, each side of the number (and does not contain numbers).
I realise I can do this in more than one line of code quite easily but it seems like this should be possible.
Using a callback function allows you to cast a match to number and increment, e.g.:
preg_replace_callback(
"/str\/(\d+)str/",
function($matches) { return "str/" . ((int)$matches[1] + 1) . "str"; },
$original
);
Solely using str_replace you can get the number from the string, add one to it, and the replace the old number with the new one :
$str = 'In My Cart : 11 items';
$nb = preg_replace('/\D/', '', $str);
$nb += 1;
$str = str_replace($nb-1, $nb, $str);
echo $str;
I am looking for some code that allows you to add +44 onto the beginning of my $string variable.
So the ending product would be:
$string = 071111111111
+44071111111111
Your $string variable isn't actually a string in this scenario; it's an integer. Make it a string by putting quotes around it:
$string = "071111111111"
Then you can use the . operator to append one string to another, so you could do this:
$string = "+44" . $string
Now $string is +44071111111111. You can read more about how to use the . (string concatenation operator) on the PHP documentation here.
Other people's suggestions of just keeping $string as an integer wouldn't work: "+44" . 071111111111 is actually +447669584457. Due to the 0 at the start of the number, PHP converts it to an octal number rather than a decimal one.
You can combine strings by .
$string = '+44'.$string;
You can use universal code, which works with another parameters too.
<?php
$code = "+44";
$string = "071111111111";
function prepend(& $string, $code) {
$test = substr_replace($string, $code, 0, 0);
echo $test;
}
prepend($string, $code);
?>
We want to censor certain words on our site but each word has different censored output.
For example:
PHP => P*P, javascript => j*vascript
(However not always the second letter.)
So we want a simple "one star" censor system but with keeping the original caps. The datas coming from the database are uncensored so we need the fastest way that possible.
$data="Javascript and php are awesome!";
$word[]="PHP";
$censor[]="H";//the letter we want to replace
$word[]="javascript";
$censor[]="a"//but only once (j*v*script would look wierd)
//Of course if it needed we can use the full censored word in $censor variables
Expected value:
J*vascript and p*p are awesome!
Thanks for all the answers!
You can put your censored words in key-based array, and value of the array should be the position of what char is replaced with * (see $censor array example bellow).
$string = 'JavaSCRIPT and pHp are testing test-ground for TEST ŠĐČĆŽ ŠĐčćŽ!';
$censor = [
'php' => 2,
'javascript' => 2,
'test' => 3,
'šđčćž' => 4,
];
function stringCensorSlow($string, array $censor) {
foreach ($censor as $word => $position) {
while (($pos = mb_stripos($string, $word)) !== false) {
$string =
mb_substr($string, 0, $pos + $position - 1) .
'*' .
mb_substr($string, $pos + $position);
}
}
return $string;
}
function stringCensorFast($string, array $censor) {
$pattern = [];
foreach ($censor as $word => $position) {
$word = '~(' . mb_substr($word, 0, $position - 1) . ')' . mb_substr($word, $position - 1, 1) . '(' . mb_substr($word, $position) . ')~iu';
$pattern[$word] = '$1*$2';
}
return preg_replace(array_keys($pattern), array_values($pattern), $string);
}
Use example :
echo stringCensorSlow($string, $censor);
# J*vaSCRIPT and p*p are te*ting te*t-ground for TE*T ŠĐČ*Ž ŠĐč*Ž!
echo stringCensorFast($string, $censor) . "\n";
# J*vaSCRIPT and p*p are te*ting te*t-ground for TE*T ŠĐČ*Ž ŠĐč*Ž!
Speed test :
foreach (['stringCensorSlow', 'stringCensorFast'] as $func) {
$time = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$func($string, $censor);
}
$time = microtime(true) - $time;
echo "{$func}() took $time\n";
}
output on my localhost was :
stringCensorSlow() took 1.9752140045166
stringCensorFast() took 0.11587309837341
Upgrade #1: added multibyte character safe.
Upgrade #2: added example for preg_replace, which is faster than mb_substr. Tnx to AbsoluteƵERØ
Upgrade #3: added speed test loop and result on my local PC machine.
Make an array of words and replacements. This should be your fastest option in terms of processing, but a little more methodical to setup. Remember when you're setting up your patterns to use the i modifier to make each pattern case insensitive. You could ultimately pull these from a database into the arrays. I've hard-coded the arrays here for the example.
<!DOCTYPE html>
<html>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<?php
$word_to_alter = array(
'!(j)a(v)a(script)(s|ing|ed)?!i',
'!(p)h(p)!i',
'!(m)y(sql)!i',
'!(p)(yth)o(n)!i',
'!(r)u(by)!i',
'!(ВЗЛ)О(М)!iu',
);
$alteration = array(
'$1*$2*$3$4',
'$1*$2',
'$1*$2',
'$1$2*$3',
'$1*$2',
'$1*$2',
);
$string = "Welcome to the world of programming. You can learn PHP, MySQL, Python, Ruby, and Javascript all at your own pace. If you know someone who uses javascripting in their daily routine you can ask them about becoming a programmer who writes JavaScripts. взлом прохладно";
$newstring = preg_replace($word_to_alter,$alteration,$string);
echo $newstring;
?>
</html>
Output
Welcome to the world of programming. You can learn P*P, M*SQL, Pyth*n,
R*by, and J*v*script all at your own pace. If you know someone who
uses j*v*scripting in their daily routine you can ask them about
becoming a programmer who writes J*v*Scripts. взл*м прохладно
Update
It works the same with UTF-8 characters, note that you have to specify a u modifier to make the pattern treated as UTF-8.
u (PCRE_UTF8)
This modifier turns on additional functionality of PCRE that is incompatible with Perl. Pattern strings are treated as UTF-8. This
modifier is available from PHP 4.1.0 or greater on Unix and from PHP
4.2.3 on win32. UTF-8 validity of the pattern is checked since PHP 4.3.5.
Why not just use a little helper function and pass it a word and the desired censor?
function censorWord($word, $censor) {
if(strpos($word, $censor)) {
return preg_replace("/$censor/",'*', $word, 1);
}
}
echo censorWord("Javascript", "a"); // returns J*avascript
echo censorWord("PHP", "H"); // returns P*P
Then you can check the word against your wordlist and if it is a word that should be censored, you can pass it to the function. Then, you also always have the original word as well as the censored one to play with or put back in your sentence.
This would also make it easy to change the number of letters censored by just changing the offset in the preg_replace. All you have to do is keep an array of words, explode the sentence on spaces or something, and then check in_array. If it is in the array, send it to censorWord().
Demo
And here's a more complete example doing exactly what you said in the OP.
function censorWord($word, $censor) {
if(strpos($word, $censor)) {
return preg_replace("/$censor/",'*', $word, 1);
}
}
$word_list = ['php','javascript'];
$data = "Javascript and php are awesome!";
$words = explode(" ", $data);
// pass each word by reference so it can be modified inside our array
foreach($words as &$word) {
if(in_array(strtolower($word), $word_list)) {
// this just passes the second letter of the word
// as the $censor argument
$word = censorWord($word, $word[1]);
}
}
echo implode(" ", $words); // returns J*vascript and p*p are awesome!
Another Demo
You could store a lowercase list of the censored words somewhere, and if you're okay with starring the second letter every time, do something like this:
if (in_array(strtolower($word), $censored_words)) {
$word = substr($word, 0, 1) . "*" . substr($word, 2);
}
If you want to change the first occurrence of a letter, you could do something like:
$censored_words = array('javascript' => 'a', 'php' => 'h', 'ruby' => 'b');
$lword = strtolower($word);
if (in_array($lword, array_keys($censored_words))) {
$ind = strpos($lword, $censored_words[$lword]);
$word = substr($word, 0, $ind) . "*" . substr($word, $ind + 1);
}
This is what I would do:
Create a simple database (text file) and make a "table" of all your censored words and expected censored results. E.G.:
PHP --- P*P
javascript --- j*vascript
HTML --- HT*L
Write PHP code to compare the database information to your simple censored file. You will have to use array explode to create an array of only words. Something like this:
/* Opening database of censored words */
$filename = "/files/censored_words.txt";
$file = fopen( $filename, "r" );
if( $file == false )
{
echo ( "Error in opening file" );
exit();
}
/* Creating an array of words from string*/
$data = explode(" ", $data); // What was "Javascript and PHP are awesome!" has
// become "Javascript", "and", "PHP", "are",
// "awesome!". This is useful.
If your script finds matching words, replace the word in your data with the censored word from your list. You would have to delimit the file first by \r\n and finally by ---. (Or whatever you choose for separating your table with.)
Hope this helped!
Please let me know how to allow less than character '<' in strip_tags()
Code Snippet
$string ="abc<123";
StringFromUser($string);
function StringFromUser($string)
{
if (is_string($string))
{
return strip_tags($string);
}
}
Output : abc
Expected output abc<123
Encode it properly in the first place.
$string ="abc<123";
Although if you're not sanitizing for HTML output you shouldn't be using strip_tags() anyway.
strip_tags is a pretty basic and not very good way to sanitize data (i.e. "punch arbitrary values into shape"). Again, it's not a very good function, as you are seeing. You should only sanitize data if you have a very good reason to, oftentimes there is no good reason. Ask yourself what you are gaining from arbitrarily stripping out parts of a value.
You either want to validate or escape to avoid syntax problems and/or injection attacks. Sanitization is rarely the right thing to do. Read The Great Escapism (Or: What You Need To Know To Work With Text Within Text) for more background on the whole topic.
You could search for a character in your string, take it out, strip_tags() your string and put the character back in:
$string = "abc<123";
$character = "<";
$pos = strpos($string,$character);
$tag = ">";
$check = strpos($string,$tag);
if ($pos !== false && $check == false) {
$string_array = explode("<",$string);
$string = $string_array[0];
$string .= $string_array[1];
$string = strip_tags($string);
$length = strlen($string);
$substr = substr($string, 0, $pos);
$substr .= "<";
$substr .= substr($string, $pos, $length);
$string = $substr;
} else {
$string = strip_tags($string);
}
or you could use preg_replace() to replace all the characters you don't want to have in your $string.
The problem:
The purpose to use trip_tags is to prevent attacking from HTML or PHP injection. However, trip_tags not only removes HTML and PHP tags, it also removes part of a math expression with a < operator. So, what we see is "abc<123" being replaced to "abc".
The solution:
What we know is a < followed by a space is not identified as HTML or PHP tags by strip_tags. So what I do is to replace "abc<123" to "abc< myUniqueID123". Please note there is a space followed the < sign. And also, only numbers followed the < sign are replaced. Next, strip_tags the string. Finally, replace "abc< myUniqueID123" back to "abc<123".
$string = "abc<123";
echo StringFromUser($string);
function StringFromUser($string)
{
if (is_string($string)) {
//change "abc<123" to "abc< myUniqueID123", so math expressions are not stripped.
//use myQuniqueID to identity what we have changed later.
$string = preg_replace("/(<)(\d)/", "$1 myUniqueID$2", $string);
$string = strip_tags($string);
//change "abc< myUniqueID123" back to "abc<123"
$string = preg_replace("/(<) myUniqueID(\d)/", "$1$2", $string);
return $string;
}
}
I have a small problem. I am tryng to convert a string like "1 234" to a number:1234
I cant't get there. The string is scraped fro a website. It is possible not to be a space there? Because I've tried methods like str_replace and preg_split for space and nothing. Also (int)$abc takes only the first digit(1).
If anyone has an ideea, I'd be greatefull! Thank you!
This is how I would handle it...
<?php
$string = "Here! is some text, and numbers 12 345, and symbols !£$%^&";
$new_string = preg_replace("/[^0-9]/", "", $string);
echo $new_string // Returns 12345
?>
intval(preg_replace('/[^0-9]/', '', $input))
Scraping websites always requires specific code, you know how you receive the input - and you write code that is required to make it usable.
That is why first answer is still str_replace.
$iInt = (int)str_replace(array(" ", ".", ","), "", $iInt);
$str = "1 234";
$int = intval(str_replace(' ', '', $str)); //1234
I've just came into the same issue, however the answer that was provided wasn't covering all the different cases I had...
So I made this function (the idea popped in my mind thanks to Dan) :
function customCastStringToNumber($stringContainingNumbers, $decimalSeparator = ".", $thousandsSeparator = " "){
$numericValues = $matches = $result = array();
$regExp = null;
$decimalSeparator = preg_quote($decimalSeparator);
$regExp = "/[^0-9$decimalSeparator]/";
preg_match_all("/[0-9]([0-9$thousandsSeparator]*)[0-9]($decimalSeparator)?([0-9]*)/", $stringContainingNumbers, $matches);
if(!empty($matches))
$matches = $matches[0];
foreach($matches as $match):
$numericValues[] = (float)str_replace(",", ".", preg_replace($regExp, "", $match));
endforeach;
$result = $numericValues;
if(count($numericValues) === 1)
$result = $numericValues[0];
return $result;
}
So, basically, this function extracts all the numbers contained inside of a string, no matter how many text there is, identifies the decimal separator and returns every extracted number as a float.
One can specify what decimal separator is used in one's country with the $decimalSeparator parameter.
Use this code for removing any other characters like .,:"'\/, !##$%^&*(), a-z, A-Z :
$string = "This string involves numbers like 12 3435 and 12.356 and other symbols like !## then the output will be just an integer number!";
$output = intval(preg_replace('/[^0-9]/', '', $string));
var_dump($output);