substr

(PHP 3, PHP 4, PHP 5)

substr -- Return part of a string

Description

string substr ( string string, int start [, int length] )

substr() returns the portion of string specified by the start and length parameters.

If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth.

例子 1. Basic substr() usage

<?php
echo substr('abcdef', 1);     // bcdef
echo substr('abcdef', 1, 3);  // bcd
echo substr('abcdef', 0, 4);  // abcd
echo substr('abcdef', 0, 8);  // abcdef
echo substr('abcdef', -1, 1); // f

// Accessing single characters in a string
// can also be achived using "curly braces"
$string = 'abcdef';
echo
$string{0};                 // a
echo $string{3};                 // d
echo $string{strlen($string)-1}; // f

?>

If start is negative, the returned string will start at the start'th character from the end of string.

例子 2. Using a negative start

<?php
$rest
= substr("abcdef", -1);    // returns "f"
$rest = substr("abcdef", -2);    // returns "ef"
$rest = substr("abcdef", -3, 1); // returns "d"
?>

If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If string is less than or equal to start characters long, FALSE will be returned.

If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative). If start denotes a position beyond this truncation, an empty string will be returned.

例子 3. Using a negative length

<?php
$rest
= substr("abcdef", 0, -1);  // returns "abcde"
$rest = substr("abcdef", 2, -1);  // returns "cde"
$rest = substr("abcdef", 4, -4);  // returns ""
$rest = substr("abcdef", -3, -1); // returns "de"
?>

See also strrchr(), substr_replace(), ereg(), trim(), mb_substr() and wordwrap().


add a note add a note User Contributed Notes
egingell at sisna dot com
19-Oct-2006 06:19
<?php

/**
 * string substrpos(string $str, mixed $start [[, mixed $end], boolean $ignore_case])
 *
 * If $start is a string, substrpos will return the string from the position of the first occuring $start to $end
 *
 * If $end is a string, substrpos will return the string from $start to the position of the first occuring $end
 *
 * If the first character in (string) $start or (string) $end is '-', the last occuring string will be used.
 *
 * If $ignore_case is true, substrpos will not care about the case.
 * If $ignore_case is false (or anything that is not (boolean) true, the function will be case sensitive.
 *        Both of the above: only applies if either $start or $end are strings.
 *
 * echo substrpos('This is a string with 0123456789 numbers in it.', 5, '5');
 *        // Prints 'is a string with 01234';
 *
 * echo substrpos('This is a string with 0123456789 numbers in it.', '5', 5);
 *        // Prints '56789'
 *
 * echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-string')
 *        // Prints 's is a string with 0123456789 numbers in it and two '
 *
 * echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-STRING', true)
 *        // Prints 's is a string with 0123456789 numbers in it and two '
 *
 * echo substrpos('This is a string with 0123456789 numbers in it and two strings.', -60, '-STRING', false)
 *        // Prints 's is a string with 0123456789 numbers in it and two strings.'
 *
 * Warnings:
 *        Since $start and $end both take either a string or an integer:
 *            If the character or string you are searching $str for is a number, pass it as a quoted string.
 *        If $end is (integer) 0, an empty string will be returned.
 *        Since this function takes negative strings ('-search_string'):
 *            If the string your using in $start or $end is a '-' or begins with a '-' escape it with a '\'.
 *            This only applies to the *first* character of $start or $end.
 */

// Define stripos() if not defined (PHP < 5).
if (!is_callable("stripos")) {
   function
stripos($str, $needle, $offset = 0) {
       return
strpos(strtolower($str), strtolower($needle), $offset);
   }
}

function
substrpos($str, $start, $end = false, $ignore_case = false) {
  
// Use variable functions
  
if ($ignore_case === true) {
      
$strpos = 'stripos'; // stripos() is included above in case it's not defined (PHP < 5).
  
} else {
      
$strpos = 'strpos';
   }

  
// If end is false, set it to the length of $str
  
if ($end === false) {
      
$end = strlen($str);
   }

  
// If $start is a string do what's needed to make it an integer position for substr().
  
if (is_string($start)) {
      
// If $start begins with '-' start processing until there's no more matches and use the last one found.
      
if ($start{0} == '-') {
          
// Strip off the '-'
          
$start = substr($start, 1);
          
$found = false;
          
$pos = 0;
           while((
$curr_pos = $strpos($str, $start, $pos)) !== false) {
              
$found = true;
              
$pos = $curr_pos + 1;
           }
           if (
$found === false) {
              
$pos = false;
           } else {
              
$pos -= 1;
           }
       } else {
          
// If $start begins with '\-', strip off the '\'.
          
if ($start{0} . $start{1} == '\-') {
              
$start = substr($start, 1);
           }
          
$pos = $strpos($str, $start);
       }
      
$start = $pos !== false ? $pos : 0;
   }

  
// Chop the string from $start to strlen($str).
  
$str = substr($str, $start);

  
// If $end is a string, do exactly what was done to $start, above.
  
if (is_string($end)) {
       if (
$end{0} == '-') {
          
$end = substr($end, 1);
          
$found = false;
          
$pos = 0;
           while((
$curr_pos = strpos($str, $end, $pos)) !== false) {
              
$found = true;
              
$pos = $curr_pos + 1;
           }
           if (
$found === false) {
              
$pos = false;
           } else {
              
$pos -= 1;
           }
       } else {
           if (
$end{0} . $end{1} == '\-') {
              
$end = substr($end, 1);
           }
          
$pos = $strpos($str, $end);
       }
      
$end = $pos !== false ? $pos : strlen($str);
   }

  
// Since $str has already been chopped at $start, we can pass 0 as the new $start for substr()
  
return substr($str, 0, $end);
}

?>
feedback at realitymedias dot com
16-Oct-2006 08:47
This function can replace substr() in some situations you don't want to cut right in the middle of a word. strtrim will cut between words when it is possible choosing the closest possible final string len to return. the maxoverflow parameter lets you choose how many characters can overflow past the maxlen parameter.

<?php

function strtrim($str, $maxlen=100, $elli=NULL, $maxoverflow=15) {
   global
$CONF;
      
   if (
strlen($str) > $maxlen) {
          
       if (
$CONF["BODY_TRIM_METHOD_STRLEN"]) {
           return
substr($str, 0, $maxlen);
       }
          
      
$output = NULL;
      
$body = explode(" ", $str);
      
$body_count = count($body);
      
      
$i=0;
  
       do {
          
$output .= $body[$i]." ";
          
$thisLen = strlen($output);
          
$cycle = ($thisLen < $maxlen && $i < $body_count-1 && ($thisLen+strlen($body[$i+1])) < $maxlen+$maxoverflow?true:false);
          
$i++;
       } while (
$cycle);
       return
$output.$elli;
   }
   else return
$str;
}

?>
joseph dot morphy at gmail dot com
17-Aug-2006 12:31
<?php
//function to get a substring between between two other substrings

function substring_between($haystack,$start,$end) {
   if (
strpos($haystack,$start) === false || strpos($haystack,$end) === false) {
       return
false;
   } else {
      
$start_position = strpos($haystack,$start)+strlen($start);
      
$end_position = strpos($haystack,$end);
       return
substr($haystack,$start_position,$end_position-$start_position);
   }
}

//use of this function to get the title of an html document

$handle = fopen($filename, 'r');
$contents = fread($handle, filesize($filename));
fclose($handle);

$contents = htmlspecialchars($contents);
$title = substring_between($contents,'&lt;title&gt;','&lt;/title&gt;');

?>
rodrigo at fabricadeideias dot com
18-Mar-2006 05:17
It might be obvious to some but I took some time to figure it out that you can't call
<?php
$text
= substr($text, 0, -0);
?>
and expect $text to be unchanged.

A bit of context might make the issue clearer. I'm calculating how many characters I need to chop of the end of the string and them I call substr as
<?php
$text
= substr($text, 0, -$charactersToChop);
?>
Sometimes $charactersToChop is set to 0 and in this case I wanted $text to be unchanged. The problem is that in this case $text gets set to an empty string.

Why? Because -0 is the same as 0 and substr($text, 0, 0) obviously returns an empty string.

In case someone want a fix:
<?php
if ($charactersToChop) {
 
$text = substr($text, 0, -$charactersToChop);
}
?>

That's it.
shadzar
13-Feb-2006 09:21
a function to read in a file and split the string into its individual characters and display them as images for a webcounter.

can be used anywhere you need to split a string where a seperator is not present and versions where the str_split() function is also not present.

<?php
//start counter
$filename = "counter_file.txt";
$pathtoiamges = "http://www.yoursite.com/counter/";//where is your iamges
$extension = ".gif";//what filetype are your images in
//--------------do not change below this line-------------------
$counter=file_get_contents($filename);
$counter++;
$count=$counter;
$current=0;
$visit=array("");//array to hold individual characters
//split string into individual characters
//same as str_split($str) in PHP5
while (strlen($count)>0)
   {
  
$current++;
  
$visit[$current]=substr($count,0,1);//get current digit
  
$count=substr($count,1,strlen($count));//reduce number string to remove last stored digit
  
}
//display images of digits
foreach ($visit as $vis)
   {
   if (
$vis!=""){echo "<img src=\"". $pathtoimages . $vis . .$extension . "\">";}
   }
$list = fopen($filename, "w+");
fwrite($list, $counter);
fclose($list);
//end counter
?>

requires a file to store the counter and 10 images to represent the digits (0-9) if used as a counter.
wishie at gmail dot com
04-Feb-2006 10:37
Here's a function I wrote that'll insert a string into another string with an offset.

// $insertstring - the string you want to insert
// $intostring - the string you want to insert it into
// $offset - the offset

function str_insert($insertstring, $intostring, $offset) {
   $part1 = substr($intostring, 0, $offset);
   $part2 = substr($intostring, $offset);
  
   $part1 = $part1 . $insertstring;
   $whole = $part1 . $part2;
   return $whole;
}
Bradley from California
11-Jan-2006 05:34
Add on to "Matias from Argentina" str_format_number function.
Just added handling of $String shorter then $Format by adding a side to start the fill and a string length to the while loop.

function str_format_number($String, $Format, $Start = 'left'){
   //If we want to fill from right to left incase string is shorter then format
   if ($Start == 'right') {
       $String = strrev($String);
       $Format = strrev($Format);
   }
   if($Format == '') return $String;
   if($String == '') return $String;   
   $Result = '';
   $FormatPos = 0;
   $StringPos = 0;
   while ((strlen($Format) - 1) >= $FormatPos && strlen($String) > $StringPos) {
       //If its a number => stores it
       if (is_numeric(substr($Format, $FormatPos, 1))) {
           $Result .= substr($String, $StringPos, 1);
           $StringPos++;
           //If it is not a number => stores the caracter
       } else {
           $Result .= substr($Format, $FormatPos, 1);
       }
       //Next caracter at the mask.
       $FormatPos++;
   }
   if ($Start == 'right') $Result = strrev($Result);
   return $Result;
}
eallik at hotmail dot com
05-Jan-2006 11:22
Be careful when comparing the return value of substr to FALSE. FALSE may be returned even if the output is a valid string.

substr("0", 0); // equals "0", comparision with FALSE evaluates to true, because "0" == 0 == FALSE
mr at bbp dot biz
14-Dec-2005 06:54
Here's a little addon to the html_substr function posted by fox.

Now it counts only chars outside of tags, and doesn't cut words.

Note: this will only work in xhtml strict/transitional due to the checking of "/>" tags and the requirement of quotations in every value of a tag. It's also only been tested with the presence of br, img, and a tags, but it should work with the presence of any tag.

<?php
function html_substr($posttext, $minimum_length = 200, $length_offset = 20, $cut_words = FALSE, $dots = TRUE) {
  
  
// $minimum_length:
   // The approximate length you want the concatenated text to be 
 

   // $length_offset:
   // The variation in how long the text can be in this example text
   // length will be between 200 and 200-20=180 characters and the
   // character where the last tag ends

   // Reset tag counter & quote checker
  
$tag_counter = 0;
  
$quotes_on = FALSE;
  
// Check if the text is too long
  
if (strlen($posttext) > $minimum_length) {
      
// Reset the tag_counter and pass through (part of) the entire text
      
$c = 0;
       for (
$i = 0; $i < strlen($posttext); $i++) {
          
// Load the current character and the next one
           // if the string has not arrived at the last character
          
$current_char = substr($posttext,$i,1);
           if (
$i < strlen($posttext) - 1) {
              
$next_char = substr($posttext,$i + 1,1);
           }
           else {
              
$next_char = "";
           }
          
// First check if quotes are on
          
if (!$quotes_on) {
              
// Check if it's a tag
               // On a "<" add 3 if it's an opening tag (like <a href...)
               // or add only 1 if it's an ending tag (like </a>)
              
if ($current_char == '<') {
                   if (
$next_char == '/') {
                      
$tag_counter += 1;
                   }
                   else {
                      
$tag_counter += 3;
                   }
               }
              
// Slash signifies an ending (like </a> or ... />)
               // substract 2
              
if ($current_char == '/' && $tag_counter <> 0) $tag_counter -= 2;
              
// On a ">" substract 1
              
if ($current_char == '>') $tag_counter -= 1;
              
// If quotes are encountered, start ignoring the tags
               // (for directory slashes)
              
if ($current_char == '"') $quotes_on = TRUE;
           }
           else {
              
// IF quotes are encountered again, turn it back off
              
if ($current_char == '"') $quotes_on = FALSE;
           }
          
          
// Count only the chars outside html tags
          
if($tag_counter == 2 || $tag_counter == 0){
              
$c++;
           }         
                          
          
// Check if the counter has reached the minimum length yet,
           // then wait for the tag_counter to become 0, and chop the string there
          
if ($c > $minimum_length - $length_offset && $tag_counter == 0 && ($next_char == ' ' || $cut_words == TRUE)) {
              
$posttext = substr($posttext,0,$i + 1);             
               if(
$dots){
                  
$posttext .= '...';
               }
               return
$posttext;
           }
       }
   } 
   return
$posttext;
}

?>
felipe at spdata dot com dot br
29-Nov-2005 08:48
JavaScript charAt PHP equivalent

<?php
  
function charAt($str, $pos)
   {
       return (
substr($str, $pos, 1)) ? substr($str, $pos, 1) : -1;
   }
?>

If found, return the charecter at the specified position, otherwise return -1
18-Oct-2005 10:47
<?php
function utf8_substr($str,$from,$len){
# utf8 substr
# www.yeap.lv
 
return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$from.'}'.
                      
'((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s',
                      
'$1',$str);
}
?>
frank at jkelloggs dot dk
26-Jul-2005 05:37
Regarding the utf8_substr function from lmak: The pattern '/./u' doesn't match newline characters. This means that the substring from 0 to the total length of the string will miss the number of characters in the end matching the number of newlines in the string. To fix this one can add the s modifier (PCRE_DOTALL) in the pattern:

<?php
function utf8_substr($str,$start)
{
  
preg_match_all("/./su", $str, $ar);

   if(
func_num_args() >= 3) {
      
$end = func_get_arg(2);
       return
join("",array_slice($ar[0],$start,$end));
   } else {
       return
join("",array_slice($ar[0],$start));
   }
}
?>
julius at infoguiden dot no
05-Jul-2005 02:23
This function shortens the string down to maximum lengt defined in $max_lengt. If the string is longer the function finds the last occurance of a space and adds three dots at the end to illustrate that it is more text. If the string is without spaces it stops at exacly max lengt, also adding three dots. If the string is shorter than max lengt it returns the string as it is. This is useful for previewing long strings.

function str_stop($string, $max_length){
   if (strlen($string) > $max_length){
       $string = substr($string, 0, $max_length);
       $pos = strrpos($string, " ");
       if($pos === false) {
               return substr($string, 0, $max_length)."...";
           }
       return substr($string, 0, $pos)."...";
   }else{
       return $string;
   }
}
php_net at thomas dot trella dot de
29-Jun-2005 11:07
I needed to cut a string after x chars at a  html converted utf-8 text (for example Japanese text like &#23344;&#35632;&#24368;&#33072;&#27440;&#32591;).
The problem was, the different length of the signs, so I wrote the following function to handle that.
Perhaps it helps.

<?php

function html_cutstr ($str, $len)
{
   if (!
preg_match('/\&#[0-9]*;.*/i', $str))
   {
      
$rVal = strlen($str, $len);
       break;
   }

  
$chars = 0;
  
$start = 0;
   for(
$i=0; $i < strlen($str); $i++)
   {
       if (
$chars >= $len)
       break;

      
$str_tmp = substr($str, $start, $i-$start);
       if (
preg_match('/\&#[0-9]*;.*/i', $str_tmp))
       {
          
$chars++;
          
$start = $i;
       }
   }
  
$rVal = substr($str, 0, $start);
   if (
strlen($str) > $start)
  
$rVal .= " ...";
   return
$rVal;
}
?>
ivanhoe011 at gmail dot com
08-Jun-2005 11:31
If you need just a single character from the string you don't need to use substr(), just use curly braces notation:

<?php
  
// both lines will output the 3rd character
  
echo substr($my_string, 2, 1);
   echo
$my_string{2}; 
?>

curly braces syntax is faster and more readable IMHO..
rob NOSPAM at clancentric dot net
07-Jun-2005 06:43
I have developed a function with a similar outcome to jay's

Checks if the last character is or isnt a space. (does it the normal way if it is)
It explodes the string into an array of seperate works, the effect is... it chops off anything after and including the last space.

<?
function limit_string($string, $charlimit)
{
   if(
substr($string,$charlimit-1,1) != ' ')
   {
      
$string = substr($string,'0',$charlimit);
      
$array = explode(' ',$string);
      
array_pop($array);
      
$new_string = implode(' ',$array);

       return
$new_string.'...';
   }
   else
   {   
       return
substr($string,'0',$charlimit-1).'...';
   }
}
?>
bleakwind at msn dot com
26-May-2005 01:11
This returns the portion of str specified by the start and length parameters..
It can performs multi-byte safe on number of characters. like mb_strcut() ...

Note:
1.Use it like this bite_str(string str, int start, int length [,byte of on string]);
2.First character's position is 0. Second character position is 1, and so on...
3.$byte is one character length of your encoding, For example: utf-8 is "3", gb2312 and big5 is "2"...you can use the function strlen() get it...
Enjoy it :) ...

--- Bleakwind
QQ:940641
http://www.weaverdream.com

PS:I'm sorry my english is too poor... :(

<?php
// String intercept By Bleakwind
// utf-8:$byte=3 | gb2312:$byte=2 | big5:$byte=2
function bite_str($string, $start, $len, $byte=3)
{
  
$str    = "";
  
$count  = 0;
  
$str_len = strlen($string);
   for (
$i=0; $i<$str_len; $i++) {
       if ((
$count+1-$start)>$len) {
          
$str  .= "...";
           break;
       } elseif ((
ord(substr($string,$i,1)) <= 128) && ($count < $start)) {
          
$count++;
       } elseif ((
ord(substr($string,$i,1)) > 128) && ($count < $start)) {
          
$count = $count+2;
          
$i    = $i+$byte-1;
       } elseif ((
ord(substr($string,$i,1)) <= 128) && ($count >= $start)) {
          
$str  .= substr($string,$i,1);
          
$count++;
       } elseif ((
ord(substr($string,$i,1)) > 128) && ($count >= $start)) {
          
$str  .= substr($string,$i,$byte);
          
$count = $count+2;
          
$i    = $i+$byte-1;
       }
   }
   return
$str;
}

// Test
$str = "123456123456123456";
for(
$i=0;$i<30;$i++){
   echo
"<br>".bite_str($str,$i,20);   
}
?>
fanfatal at fanfatal dot pl
17-May-2005 02:45
Hmm ... this is a script I wrote, whitch is very similar to substr, but it isn't takes html and bbcode for counting and it takes portion of string and show avoided (html & bbcode) tags too ;]
Specially usefull for show part of serach result included html and bbcode tags

<?php

/**
 * string csubstr ( string string, int start [, int length] )
 *
 * @author FanFataL
 * @param string string
 * @param int start
 * @param [int length]
 * @return string
 */
function csubstr($string, $start, $length=false) {
  
$pattern = '/(\[\w+[^\]]*?\]|\[\/\w+\]|<\w+[^>]*?>|<\/\w+>)/i';
  
$clean = preg_replace($pattern, chr(1), $string);
   if(!
$length)
      
$str = substr($clean, $start);
   else {
      
$str = substr($clean, $start, $length);
      
$str = substr($clean, $start, $length + substr_count($str, chr(1)));
   }
  
$pattern = str_replace(chr(1),'(.*?)',preg_quote($str));
   if(
preg_match('/'.$pattern.'/is', $string, $matched))
       return
$matched[0];
   return
$string;
}

?>

Using this is similar to simple substr.

Greatings ;]
...
mike at go dot online dot pt
07-May-2005 11:15
matt at spcan dot com
04-May-2005 02:47
substr($lbar_html,0,-2); // does not work

and

substr($lbar_html, 0, -2); // works as expected

do not work the same.
woutermb at gmail dot com
22-Mar-2005 03:19
Well this is a script I wrote, what it does is chop up long words with malicious meaning into several parts. This way, a chat in a table will not get stretched anymore.

<?php

function text($string,$limit=20,$chop=10){

$text = explode(" ",$string);
while(list(
$key, $value) = each($text)){
  
$length = strlen($value);
   if(
$length >=20){
       for(
$i=0;$i<=$length;$i+=10){
          
$new .= substr($value, $i, 10);
          
$new .= " ";
       }
        
$post .= $new;
   }
   elseif(
$length <=15){
      
$post .= $value;
   }
  
$post .= " ";
}
return(
$post);
}

// for example, this would return:
$output = text("Well this text doesn't get cut up, yet thisssssssssssssssssssssssss one does.", 10, 5);

echo(
$output); // "Well this text doesn't get cup up, yet thiss sssss sssss sssss sssss sss one does."
?>

I hope it was useful.. :)
steve at unicycle dot co dot nz
14-Mar-2005 01:34
To quickly trim an optional trailing slash off the end of a path name:

if (substr( $path, -1 ) == '/') $path = substr( $path, 0, -1 );
cody at apparitiondesigns dot com
11-Mar-2005 05:02
I don't know if I didn't realize this because I'm not very smart - or if i just over looked it, but the string needs to be a string.  Not an integer.

ex.

<?php
$var
= 12345;
  echo
$var{0}; // outputs nothing at all

$var = '12345';
  echo
$var{0}; // out puts 1
?>
Matias from Argentina
25-Feb-2005 04:55
Hello,
Here you are a function to format your
numeric strings. Enjoy it.

<?php
function str_format_number($String, $Format){
   if (
$Format == '') return $String;
   if (
$String == '') return $String;

  
$Result = '';
  
$FormatPos = 0;
  
$StringPos = 0;
   While ((
strlen($Format) - 1) >= $FormatPos){
      
//If its a number => stores it
      
if (is_numeric(substr($Format, $FormatPos, 1))){
          
$Result .= substr($String, $StringPos, 1);
          
$StringPos++;
      
//If it is not a number => stores the caracter
      
} Else {
          
$Result .= substr($Format, $FormatPos, 1);
       }
      
//Next caracter at the mask.
      
$FormatPos++;
   }

   return
$Result;
}

// For phone numbers at Buenos Aires, Argentina
// Example 1:
  
$String = "541143165500";
  
$Format = "+00 00 0000.000";
   Echo
str_format_number($String, $Format); // Returns "+54 11 4316.5500"

// Example 2:
  
$String = "541143165500";
  
$Format = "+00 00 0000.0000000";
   Echo
str_format_number($String, $Format); // Returns "+54 11 4316.5500"

// Example 3:
  
$String = "541143165500";
  
$Format = "+00 00 0000.000 a";
   Echo
str_format_number($String, $Format); // Returns "+54 11 4316.550 a"

?>

How it works explanation:

str_format_number($String, $Format)
Spects two parameters $String and $Format,
both should be strings.
$String: coulbe any kind of data type,
but it's oriented to numeric string, like
phone numbers.
$Format: should be a conjunction between
numbers (any one) and others caracters.

str_format_number takes each caracter
of $Format, if it isn't a number stores
it to be returned later, but if it is a
number takes the caracter of $String
placed in the position corresponding to
the amount of numbers in $Format so far
starting from zero.

If $Format has less numbers than $string
caracters the rest of the caracters at
the end of $String should be ignored.
If $Format has more numbers than $string
caracters the no caracter will be used,
so those will be ignored.
crashmanATgreenbomberDOTcom
22-Feb-2005 10:34
A fellow coder pointed out to me that $string{-n} will no longer return the character at postion -n is. Use $string{strlen($string) - n) instead.
andrewmclagan at gmail dot com
20-Feb-2005 05:58
Hi there here is a little function i wrote to limit the number of lines in a string, i could not find anything else like it out there   

function lineLimiter ($string = "", $max_lines = 1) {
  
         $string = ereg_replace("\n", "##", $string);
  
         $totalLines = (substr_count($string, '##') + 1);
  
         $string = strrev($string);
  
         $stringLength = strlen($string);
                    
         while ($totalLines > $max_lines) {
             $pos = 0;
             $pos = strpos ( $string, "##") + 2;
             //$pos = $pos - $stringLength;
             $string = substr($string, $pos);
             $totalLines--;   
         }
         $string = strrev($string);
         $string = ereg_replace("##", "\n", $string);
         return $string;
   }
Robert
14-Feb-2005 12:36
It is also good to use substr() to get a file extension when manipulating with files. For example:

<?php
$dir
= "/full/path/to/folder";
if(
is_dir($dir))
{
  if(
$dh = opendir($dir))
  {
   while((
$file = readdir($dh)) !== false)
   {
     if(
substr($file,strlen($file)-4,4) == ".txt")
     {
       echo
"Filename: $file<br/>\n";
     }
   }
  
closedir($dh);
  }
  else
  {
   echo
"Cannot open directory";
  }
}
else
{
  echo
"Cannot open directory";
}
?>

Hopefully this helps
mancini at nextcode dot org
05-Feb-2005 07:10
here are two functions to shrink a string to specified lenght , normally (stri...) or reversed (...ing)

<?php

//limit chars
 
function limitch($value,$lenght){
         if (
strlen($value) >= $lenght ){       
                
$limited = substr($value,0,$lenght);
                
$limited .= "...";                 
         }
         return
$limited;
  }
//limit chars reversed
 
function limitchrev($value,$lenght){
         if (
strlen($value) >= $lenght ){
                
$start = strlen($value)- $lenght;
                
$limited = "...";                 
                
$limited .= substr($value,$start,$lenght);
         }
         return
$limited;
  }
 
?>
vitalic#pisem.net
15-Dec-2004 07:26
Split $string after each $pos, by $space
Example: <?php spaceStr('1836254','-',3); ?>
Would return '183-625-4';

<?php
function spaceStr($string,$space,$pos)
{
      
$cpos=$pos;
       while (
$cpos<strlen($string))
       {
        
$string=substr($string,0,$cpos).$space.substr($string,$cpos);
        
$cpos+=strlen($space)+$pos;
       };
       return
$string;
}

?>
kovacsendre at no_spam_thanks_kfhik dot hungary
02-Nov-2004 11:38
Here are the replacement functions for substr() and strlen() I use when support for html entities is required:

<?php

function html_strlen($str) {
 
$chars = preg_split('/(&[^;\s]+;)|/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  return
count($chars);
}

function
html_substr($str, $start, $length = NULL) {
  if (
$length === 0) return ""; //stop wasting our time ;)

  //check if we can simply use the built-in functions
 
if (strpos($str, '&') === false) { //No entities. Use built-in functions
  
if ($length === NULL)
     return
substr($str, $start);
   else
     return
substr($str, $start, $length);
  }

 
// create our array of characters and html entities
 
$chars = preg_split('/(&[^;\s]+;)|/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE);
 
$html_length = count($chars);

 
// check if we can predict the return value and save some processing time
 
if (
       (
$html_length === 0) /* input string was empty */ or
       (
$start >= $html_length) /* $start is longer than the input string */ or
       (isset(
$length) and ($length <= -$html_length)) /* all characters would be omitted */
    
)
   return
"";

 
//calculate start position
 
if ($start >= 0) {
  
$real_start = $chars[$start][1];
  } else {
//start'th character from the end of string
  
$start = max($start,-$html_length);
  
$real_start = $chars[$html_length+$start][1];
  }

  if (!isset(
$length)) // no $length argument passed, return all remaining characters
  
return substr($str, $real_start);
  else if (
$length > 0) { // copy $length chars
  
if ($start+$length >= $html_length) { // return all remaining characters
    
return substr($str, $real_start);
   } else {
//return $length characters
    
return substr($str, $real_start, $chars[max($start,0)+$length][1] - $real_start);
   }
  } else {
//negative $length. Omit $length characters from end
    
return substr($str, $real_start, $chars[$html_length+$length][1] - $real_start);
  }

}

?>

Example:
 
html_substr("&aacute;bla&#54;bla", 1, 4) -> "bla&#54;"

If you happen to find any bugs, please let me know.
lmak at NOSPAM dot iti dot gr
18-Aug-2004 02:59
Regarding windix's function to handle UTF-8 strings: one can use the "u" modifier on the regular expression so that the pattern string is treated as UTF-8 (available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32). This way the function works for other encodings too (like Greek for example).

The modified function would read like this:

<?php
function utf8_substr($str,$start)
{
  
preg_match_all("/./u", $str, $ar);

   if(
func_num_args() >= 3) {
      
$end = func_get_arg(2);
       return
join("",array_slice($ar[0],$start,$end));
   } else {
       return
join("",array_slice($ar[0],$start));
   }
}
?>
squeegee
11-Aug-2004 10:34
php equivalent of Javascript's substring:

<?php

function substring($str,$start,$end){
   return
substr($str,$start,($end-$start));
}

?>
fox at conskript dot server
11-Aug-2004 07:01
Here's a little bit of code to chop strings (with html tags) around a specified length while making sure no html tags are chopped. It also prevents chopping while a tag is still open.

Note: this will only work in xhtml strict/transitional due to the checking of "/>" tags and the requirement of quotations in every value of a tag. It's also only been tested with the presence of br, img, and a tags, but it should work with the presence of any tag.

<?php
function html_substr($posttext, $minimum_length, $length_offset) {
  
// The approximate length you want the concatenated text to be
  
$minimum_length = 200;
  
// The variation in how long the text can be
   // in this example text length will be between 200-10=190 characters
   // and the character where the last tag ends
  
$length_offset = 10;
  
// Reset tag counter & quote checker
  
$tag_counter = 0;
  
$quotes_on = FALSE;
  
// Check if the text is too long
  
if (strlen($posttext) > $minimum_length) {
      
// Reset the tag_counter and pass through (part of) the entire text
      
for ($i = 0; $i < strlen($posttext); $i++) {
          
// Load the current character and the next one
           // if the string has not arrived at the last character
          
$current_char = substr($posttext,$i,1);
           if (
$i < strlen($posttext) - 1) {
              
$next_char = substr($posttext,$i + 1,1);
           }
           else {
              
$next_char = "";
           }
          
// First check if quotes are on
          
if (!$quotes_on) {
              
// Check if it's a tag
               // On a "<" add 3 if it's an opening tag (like <a href...)
               // or add only 1 if it's an ending tag (like </a>)
              
if ($current_char == "<") {
                   if (
$next_char == "/") {
                                      
$tag_counter++;
                   }
                   else {
                      
$tag_counter = $tag_counter + 3;
                   }
               }
              
// Slash signifies an ending (like </a> or ... />)
               // substract 2
              
if ($current_char == "/") $tag_counter = $tag_counter - 2;
              
// On a ">" substract 1
              
if ($current_char == ">") $tag_counter--;
              
// If quotes are encountered, start ignoring the tags
               // (for directory slashes)
              
if ($current_char == "\"") $quotes_on = TRUE;
           }
           else {
              
// IF quotes are encountered again, turn it back off
              
if ($current_char == "\"") $quotes_on = FALSE;
           }
                          
          
// Check if the counter has reached the minimum length yet,
           // then wait for the tag_counter to become 0, and chop the string there
          
if ($i > $minimum_length - $length_offset && $tag_counter == 0) {
              
$posttext = substr($posttext,0,$i + 1) . "...";
               return
$posttext;
           }
       }
   }
             return
$posttext;
}
biohazard at online dot ge
16-May-2004 04:55
may be by following functions will be easyer to extract the
needed sub parts from a string:

 after ('@', 'biohazard@online.ge');
 returns 'online.ge'
 from the first occurrence of '@'

 before ('@', 'biohazard@online.ge');
 returns 'biohazard'
 from the first occurrence of '@'

 between ('@', '.', 'biohazard@online.ge');
 returns 'online'
 from the first occurrence of '@'

 after_last ('[', 'sin[90]*cos[180]');
 returns '180]'
 from the last occurrence of '['

 before_last ('[', 'sin[90]*cos[180]');
 returns 'sin[90]*cos['
 from the last occurrence of '['

 between_last ('[', ']', 'sin[90]*cos[180]');
 returns '180'
 from the last occurrence of '['
 

<?

  
function after ($this, $inthat)
   {
       if (!
is_bool(strpos($inthat, $this)))
       return
substr($inthat, strpos($inthat,$this)+strlen($this));
   };

   function
after_last ($this, $inthat)
   {
       if (!
is_bool(strrevpos($inthat, $this)))
       return
substr($inthat, strrevpos($inthat, $this)+strlen($this));
   };

   function
before ($this, $inthat)
   {
       return
substr($inthat, 0, strpos($inthat, $this));
   };

   function
before_last ($this, $inthat)
   {
       return
substr($inthat, 0, strrevpos($inthat, $this));
   };

   function
between ($this, $that, $inthat)
   {
     return
before($that, after($this, $inthat));
   };

   function
between_last ($this, $that, $inthat)
   {
     return
after_last($this, before_last($that, $inthat));
   };

  
// USES
  
function strrevpos($instr, $needle)
   {
      
$rev_pos = strpos (strrev($instr), strrev($needle));
       if (
$rev_pos===false) return false;
       else return
strlen($instr) - $rev_pos - strlen($needle);
   };

?>
phplist at boonedocks dot net
29-Aug-2003 04:39
If 'start' is negative and greater than the length of the string, PHP seems to return the first 'length' characters of the string. For example, substr('test',-10,1) returns 't'.
06-Jul-2003 08:39
If you want to substring the middle of a string with another and keep the words intact:

<?php
/**
 * Reduce a string by the middle, keeps whole words together
 *
 * @param string $string
 * @param int $max (default 50)
 * @param string $replacement (default [...])
 * @return string
 * @author david at ethinkn dot com
 * @author loic at xhtml dot ne
 * @author arne dot hartherz at gmx dot net
 */

function strMiddleReduceWordSensitive ($string, $max = 50, $rep = '[...]') {
  
$strlen = strlen($string);

   if (
$strlen <= $max)
       return
$string;

  
$lengthtokeep = $max - strlen($rep);
  
$start = 0;
  
$end = 0;

   if ((
$lengthtokeep % 2) == 0) {
      
$start = $lengthtokeep / 2;
      
$end = $start;
   } else {
      
$start = intval($lengthtokeep / 2);
      
$end = $start + 1;
   }

  
$i = $start;
  
$tmp_string = $string;
   while (
$i < $strlen) {
       if (
$tmp_string[$i] == ' ') {
          
$tmp_string = substr($tmp_string, 0, $i) . $rep;
          
$return = $tmp_string;
       }
      
$i++;
   }

  
$i = $end;
  
$tmp_string = strrev ($string);
   while (
$i < $strlen) {
       if (
$tmp_string[$i] == ' ') {
          
$tmp_string = substr($tmp_string, 0, $i);
          
$return .= strrev ($tmp_string);
       }
      
$i++;
   }
   return
$return;
   return
substr($string, 0, $start) . $rep . substr($string, - $end);
}

echo
strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30) . "\n";
// Returns: ABCDEEF GHIJK[...]asdf sadf sad s (33 chrs)
echo strMiddleReduceWordSensitive ('ABCDEEF GHIJK LLKJHKHKJHKL HGHFK sdfasdfsdafsdf sadf asdf sadf sad s', 30, '...') . "\n";
// Returns: ABCDEEF GHIJK...asdf sadf sad s (32 chrs)
?>