PHPのお勉強!

PHP TOP

substr

(PHP 4, PHP 5, PHP 7, PHP 8)

substr文字列の一部分を返す

説明

substr(string $string, int $offset, ?int $length = null): string

文字列 string の、offset で指定された位置から length バイト分の文字列を返します。

パラメータ

string

入力文字列。

offset

offset が正の場合、返される文字列は、 string の 0 から数えて offset番目から始まる文字列となります。 例えば、文字列'abcdef'において位置 0にある文字は、'a'であり、 位置2には'c'があります。

offset が負の場合、返される文字列は、 stringの後ろから数えて offset番目から始まる文字列となります。

string の長さが offset 文字より短い場合は、 空の文字列が返されます。

例1 負の offset の使用

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

length

length が指定され、かつ正である場合、 返される文字列は offset (string の長さに依存します) から数えてlength文字数分となります。

length が指定され、かつ負である場合、 string の終端からその文字数分の文字が省略されます (offset が負の場合は、 開始位置を算出したあとで)。 もし offset が切り出し位置を超える場合、 空の文字列が返されます。

length が指定され、かつ 0 であれば、空の文字が返されます。

length を省略した場合、または null の場合は、 offset の位置から文字列の最後までの部分文字列を返します。

例2 負の length の使用

<?php
$rest
= substr("abcdef", 0, -1); // "abcde" を返す
$rest = substr("abcdef", 2, -1); // "cde" を返す
$rest = substr("abcdef", 4, -4); // "" を返す。PHP 8.0.0 より前のバージョンでは、false を返していました。
$rest = substr("abcdef", -3, -1); // "de" を返す
?>

戻り値

string の一部を返すか、空文字列を返します。

変更履歴

バージョン 説明
8.0.0 length は、nullable になりました。 length に明示的に null を設定すると、 文字列の最後までを含む部分文字列を返すようになっています。 これより前のバージョンでは、空文字列を返していました。
8.0.0 この関数は、前のバージョンで false を返す場合に、空文字列を返すようになりました。

例3 基本的な substr() の使用法

<?php
echo substr('abcdef', 1); // bcdef
echo substr("abcdef", 1, null); // bcdef, PHP 8.0.0 より前のバージョンでは、空の文字列を返していました。
echo substr('abcdef', 1, 3); // bcd
echo substr('abcdef', 0, 4); // abcd
echo substr('abcdef', 0, 8); // abcdef
echo substr('abcdef', -1, 1); // f

// 文字列中の 1 文字にアクセスすることも
// "角括弧" を使用することで可能
$string = 'abcdef';
echo
$string[0]; // a
echo $string[3]; // d
echo $string[strlen($string)-1]; // f

?>

例4 substr() でのキャストの挙動

<?php
class apple {
public function
__toString() {
return
"green";
}
}

echo
"1) ".var_export(substr("pear", 0, 2), true).PHP_EOL;
echo
"2) ".var_export(substr(54321, 0, 2), true).PHP_EOL;
echo
"3) ".var_export(substr(new apple(), 0, 2), true).PHP_EOL;
echo
"4) ".var_export(substr(true, 0, 1), true).PHP_EOL;
echo
"5) ".var_export(substr(false, 0, 1), true).PHP_EOL;
echo
"6) ".var_export(substr("", 0, 1), true).PHP_EOL;
echo
"7) ".var_export(substr(1.2e3, 0, 4), true).PHP_EOL;
?>

上の例の出力は以下となります。

1) 'pe'
2) '54'
3) 'gr'
4) '1'
5) ''
6) ''
7) '1200'

例5 文字列の範囲が不正な場合

指定された文字列の範囲が正しくない場合、 substr() は PHP 8.0.0 以降では空文字列を返します。 それより前のバージョンでは、false を返していました。

<?php
var_dump
(substr('a', 2));
?>

上の例の PHP 8 での出力は、このようになります。:

string(0) ""

上の例の PHP 7 での出力は、このようになります。

bool(false)

参考

add a note

User Contributed Notes 34 notes

up
180
Andreas Bur (andreas dot buro at gmail dot com)
15 years ago
For getting a substring of UTF-8 characters, I highly recommend mb_substr

<?php
$utf8string
= "cakeæøå";

echo
substr($utf8string,0,5);
// output cake#
echo mb_substr($utf8string,0,5,'UTF-8');
//output cakeæ
?>
up
116
biohazard dot ge at gmail dot com
11 years ago
may be by following functions will be easier to extract the needed sub parts from a string:

<?php
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 '['
?>

here comes the source:

<?php

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

// use strrevpos function in case your php version does not include it
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);
};
?>
up
12
greg at apparel dot com
11 years ago
Coming to PHP from classic ASP I am used to the Left() and Right() functions built into ASP so I did a quick PHPversion. hope these help someone else making the switch

function left($str, $length) {
return substr($str, 0, $length);
}

function right($str, $length) {
return substr($str, -$length);
}
up
13
pugazhenthi k
11 years ago
<?Php

### SUB STRING BY WORD USING substr() and strpos() #####

### THIS SCRIPT WILL RETURN PART OF STRING WITHOUT WORD BREAK ###

$description = ‘your description here your description here your description here your description here your description here your description here your description hereyour description here your description here’ // your description here .

$no_letter = 30 ;

if(
strlen($desctiption) > 30 )
{
echo
substr($description,0,strpos($description,’ ‘,30)); //strpos to find ‘ ‘ after 30 characters.
}
else {
echo
$description;
}

?>
up
6
fatihmertdogancan at hotmail dot com
10 years ago
[English]
I created python similar accesing list or string with php substr & strrev functions.

Use: str($string,$pattern)

About the python pattern,
http://docs.python.org/release/1.5.1p1/tut/strings.html
http://effbot.org/zone/python-list.htm

About of pattern structures
[start:stop:step]

Example,
<?php
$s
= "fatihmertdogancan";
echo
str($s,"1:9:-2");
echo
"<br/>";
echo
str($s,"1:-3:-2");
echo
"<br/>";
echo
str($s,"1:-11:-5");
echo
"<br/>";
echo
str($s,"1:9:4");
?>

Output,
thetoacn
eht
aom
htan

This is function phpfiddle link: http://phpfiddle.org/main/code/e82-y5d

or source;

<?php
function str($str,$pattern){
//[start:stop:step]
//pattern -> ([-]?[0-9]*|\s):([-]?[0-9]*|\s):([-]?[0-9]*|\s)
preg_match("/([-]?[0-9]*|\s?):([-]?[0-9]*|\s?):?([-]?[0-9]*|\s?)/", $pattern, $yakala);
$start = $yakala[1];
$stop = $yakala[2];
$step = $yakala[3];

if(empty(
$start) && empty($stop) && $step == "-1"){//istisna durum
return strrev($str);
}else if(empty(
$start) && empty($stop) && isset($step)){//istisna durum
$rev = "";
$yeni = "";
if(
$step[0] == "-" && $stop != "-1"){$rev = "VAR";}
$atla = abs($step);
for(
$i = 0; $i <= strlen($str); $i++){
$offset = $i*$atla;
if(isset(
$str[$offset])){
$yeni = $yeni.$str[$offset];
}
}
if(
$rev != "VAR"){
return
substr($yeni,0,strlen($str)-1);
//"hepsi boş, step dolu o da +";
}else{
return
strrev(substr($yeni,0,strlen($str)-1));
//"hepsi boş, step dolu o da -";
}
}

if(empty(
$start) && empty($stop) && empty($step)){
return
$str;
//"hepsi boş";
}else if(empty($start)){
if(isset(
$stop) && empty($step)){
$rev = "";
if(
$stop[0] == "-"){$rev = "VAR";}
if(
$rev != "VAR"){
return
substr($str,0,$stop);
//"start ve step boş, stop dolu"
}else{
return
strrev(substr($str,0,$stop));
//"start ve step boş, stop -1";
}
}else if(isset(
$stop) && isset($step)){
$rev = "";
if(
$stop[0] == "-"){$rev = "VAR";}
$yeni = "";
if(
$step == 1){
if(
$rev != "VAR"){
return
$str;
//"start boş, stop ve step dolu, step 1";
}else{
return
strrev(substr($str,0,abs($stop))); //abs -> mutlak değer (-5 = 5)
//"start boş, stop -, step dolu, step 1";
}
}else{
$atla = abs($step);
for(
$i = 0; $i <= strlen($str); $i++){
$offset = $i*$atla;
if(isset(
$str[$offset])){
$yeni = $yeni.$str[$offset];
}
}
if(
$rev != "VAR"){
return
substr($yeni,0,$stop);
//"start boş, step ve stop dolu";
}else{
return
strrev(substr($yeni,0,abs($stop)));
//"start boş, step ve stop -";
}
}
}
//start boş değilse
}else if(!empty($start)){
if(isset(
$stop) && empty($step)){
$rev = "";
if(
$stop[0] == "-"){$rev = "VAR";}
if(
$rev != "VAR"){
return
substr($str,$start,$stop);
//return "step boş, start ve stop dolu";
}else{
return
strrev(substr($str,0,abs($stop)));
//"step boş, start ve stop dolu, stop -";
}
}else if(isset(
$stop) && isset($step)){

//hepsi dolu
$rev = "";
if(
$stop[0] == "-"){$rev = "VAR";}
$yeni = "";
if(
$step == 1){
if(
$rev != "VAR"){
return
substr($str,$start,$stop);
//"hepsi dolu, step 1";
}else{
return
substr($str,$start,abs($stop));
//"hepsi dolu, step 1, stop -";
}
}else{
if(
$stop[0] == "-"){$rev = "VAR";}
$atla = abs($step);
for(
$i = 0; $i <= strlen($str); $i++){
$offset = $i*$atla;
if(isset(
$str[$offset])){
$yeni = $yeni.$str[$offset];
}
}
if(
$rev != "VAR"){
return
substr($yeni,$start,$stop);
//"hepsi dolu";
}else{
return
strrev(substr($yeni,$start,abs($stop)));
//"hepsi dolu, stop -";
}
}
}
}
}
?>

Good works..
up
4
bleakwind at msn dot com
19 years ago
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 = "123456???ֽ?123456?ַ???123456??ȡ????";
for(
$i=0;$i<30;$i++){
echo
"<br>".bite_str($str,$i,20);
}
?>
up
8
Petez
17 years ago
I wanted to work out the fastest way to get the first few characters from a string, so I ran the following experiment to compare substr, direct string access and strstr:

<?php
/* substr access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
$opening = substr($string,0,11);
if (
$opening == 'Lorem ipsum'){
true;
}else{
false;
}
}
$endtime1 = endTimer();

/* direct access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
if (
$string[0] == 'L' && $string[1] == 'o' && $string[2] == 'r' && $string[3] == 'e' && $string[4] == 'm' && $string[5] == ' ' && $string[6] == 'i' && $string[7] == 'p' && $string[8] == 's' && $string[9] == 'u' && $string[10] == 'm'){
true;
}else{
false;
}
}
$endtime2 = endTimer();

/* strstr access */
beginTimer();
for (
$i = 0; $i < 1500000; $i++){
$opening = strstr($string,'Lorem ipsum');
if (
$opening == true){
true;
}else{
false;
}
}
$endtime3 = endTimer();

echo
$endtime1."\r\n".$endtime2."\r\n".$endtime3;
?>

The string was 6 paragraphs of Lorem Ipsum, and I was trying match the first two words. The experiment was run 3 times and averaged. The results were:

(substr) 3.24
(direct access) 11.49
(strstr) 4.96

(With standard deviations 0.01, 0.02 and 0.04)

THEREFORE substr is the fastest of the three methods for getting the first few letters of a string.
up
4
nikolai dot wuestemann at t-online dot de
13 years ago
If you want to have a string BETWEEN two strings, just use this function:

<?php
function get_between($input, $start, $end)
{
$substr = substr($input, strlen($start)+strpos($input, $start), (strlen($input) - strpos($input, $end))*(-1));
return
$substr;
}

//Example:

$string = "123456789";
$a = "12";
$b = "9";

echo
get_between($string, $a, $b);

//Output:
//345678
?>
up
2
Anonymous
7 years ago
Be aware of a slight inconsistency between substr and mb_substr

mb_substr("", 4); returns empty string

substr("", 4); returns boolean false

tested in PHP 7.1.11 (Fedora 26) and PHP 5.4.16 (CentOS 7.4)
up
3
egingell at sisna dot com
18 years ago
<?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);
}

?>
up
6
fanfatal at fanfatal dot pl
19 years ago
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 ;]
...
up
2
kaysar in ymail in com
15 years ago
Drop extensions of a file (even from a file location string)

<?php

$filename
= "c:/some dir/abc defg. hi.jklmn";

echo
substr($filename, 0, (strlen ($filename)) - (strlen (strrchr($filename,'.'))));

?>

output: c:/some dir/abc defg. hi

Hope it may help somebody like me.. (^_^)