strtok

(PHP 3, PHP 4, PHP 5)

strtok - Разбивает строку

Описание

string strtok ( string arg1, string arg2 )

strtok() разбивает строку arg1 на подстроки, используя в качестве разделителей символы из arg2. Например строку "This is an example string" можно разбить на отдельные слова.

Пример 1. Пример использования strtok()
$string = "This is\tan example\nstring";
/* в качестве разделителей используем пробел, табуляцию и перевод строки */
$tok = strtok($string, " \n\t");
while ($tok) {
    echo "Word=$tok<br />";
    $tok = strtok(" \n\t");
}

Заметьте, что исходная строка передается только при первом вызове этой функции. Последующим вызовам передаются только разделители, так как эта функция сохраняет исходную строку и запоминает позицию в этой строке между вызовами. Для работы с новой строкой нужно снова вызвать функцию с двумя аргументами.

Начиная с PHP 4.1.0, был изменен способ обработки пустых подстрок. До версии 4.1.0 эта функция возвращала пустые подстроки, а начиная с 4.1.0 эти подстроки пропускаются.

Пример 2. Старый способ обработки пустых подстрок функцией strtok()
$first_token  = strtok('/something', '/');
$second_token = strtok('/');
var_dump($first_token, $second_token);

Вывод:

string(0) "" string(9) "something"
Пример 3. Новый способ обработки пустых подстрок функцией strtok()
$first_token  = strtok('/something', '/');
$second_token = strtok('/');
var_dump($first_token, $second_token);

Вывод:

string(9) "something" bool(false)

Помните также о том, что может быть возвращена подстрока "0". В логических выражениях это значение может соответствовать FALSE.

Пример 4.
/** get leading, trailing, and embedded separator tokens that were 'skipped'
if for some ungodly reason you are using php to implement a simple parser that
needs to detect nested clauses as it builds a parse tree */
$str = "(((alpha(beta))(gamma))";
$seps = '()';
$tok = strtok( $str,$seps ); // return false on empty string or null
$cur = 0;     
$dumbDone = FALSE;
$done = (FALSE===$tok);
while (!$done) {
   // process skipped tokens (if any at first iteration) (special for last)
   $posTok = $dumbDone ? strlen($str) : strpos($str, $tok, $cur );
   $skippedMany = substr( $str, $cur, $posTok-$cur ); // false when 0 width
   $lenSkipped = strlen($skippedMany); // 0 when false
   if (0!==$lenSkipped) {
      $last = strlen($skippedMany) -1;
      for($i=0; $i<=$last; $i++){
         $skipped = $skippedMany[$i];
         $cur += strlen($skipped);
         echo "skipped: $skipped\n";
      }
   }
   if ($dumbDone) break; // this is the only place the loop is terminated
   // process current tok
   echo "curr tok: ".$tok."\n";
   // update cursor
   $cur += strlen($tok);
   // get any next tok
   if (!$dumbDone){
      $tok = strtok($seps);
      $dumbDone = (FALSE===$tok);
      // you're not really done till you check for trailing skipped
   }
};
Пример 5.
#_____________________
# parse_cli($string) /
function parse_cli($string) {
    $state = 'space';
    $previous = '';     // stores current state when encountering a backslash (which changes $state to 'escaped', but has to fall back into the previous $state afterwards)
    $out = array();     // the return value
    $word = '';
    $type = '';         // type of character
    // array[states][chartypes] => actions
    $chart = array(
        'space'        => array('space'=>'',   'quote'=>'q',  'doublequote'=>'d',  'backtick'=>'b',  'backslash'=>'ue', 'other'=>'ua'),
        'unquoted'     => array('space'=>'w ', 'quote'=>'a',  'doublequote'=>'a',  'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
        'quoted'       => array('space'=>'a',  'quote'=>'w ', 'doublequote'=>'a',  'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
        'doublequoted' => array('space'=>'a',  'quote'=>'a',  'doublequote'=>'w ', 'backtick'=>'a',  'backslash'=>'e',  'other'=>'a'),
        'backticked'   => array('space'=>'a',  'quote'=>'a',  'doublequote'=>'a',  'backtick'=>'w ', 'backslash'=>'e',  'other'=>'a'),
        'escaped'      => array('space'=>'ap', 'quote'=>'ap', 'doublequote'=>'ap', 'backtick'=>'ap', 'backslash'=>'ap', 'other'=>'ap'));
    for ($i=0; $i<=strlen($string); $i++) {
        $char = substr($string, $i, 1);
        $type = array_search($char, array('space'=>' ', 'quote'=>'\'', 'doublequote'=>'"', 'backtick'=>'`', 'backslash'=>'\\'));
        if (! $type) $type = 'other';
        if ($type == 'other') {
            // grabs all characters that are also 'other' following the current one in one go
            preg_match("/[ \'\"\`\\\]/", $string, $matches, PREG_OFFSET_CAPTURE, $i);
            if ($matches) {
                $matches = $matches[0];
                $char = substr($string, $i, $matches[1]-$i); // yep, $char length can be > 1
                $i = $matches[1] - 1;
            }else{
                // no more match on special characters, that must mean this is the last word!
                // the .= hereunder is because we *might* be in the middle of a word that just contained special chars
                $word .= substr($string, $i);
                break; // jumps out of the for() loop
            }
        }
        $actions = $chart[$state][$type];
        for($j=0; $j<strlen($actions); $j++) {
            $act = substr($actions, $j, 1);
            if ($act == ' ') $state = 'space';
            if ($act == 'u') $state = 'unquoted';
            if ($act == 'q') $state = 'quoted';
            if ($act == 'd') $state = 'doublequoted';
            if ($act == 'b') $state = 'backticked';
            if ($act == 'e') { $previous = $state; $state = 'escaped'; }
            if ($act == 'a') $word .= $char;
            if ($act == 'w') { $out[] = $word; $word = ''; }
            if ($act == 'p') $state = $previous;
        }
    }
    if (strlen($word)) $out[] = $word;
    return $out;
}
Пример 6.
/**
* The TokenIterator class allows you to iterate through string tokens using
* the familiar foreach control structure.
*
* Example:
*
*/
class TokenIterator implements Iterator
{
    /**
     * The string to tokenize.
     * @var string
     */
    protected $_string;
   
    /**
     * The token delimiters.
     * @var string
     */
    protected $_delims;
   
    /**
     * Stores the current token.
     * @var mixed
     */
    protected $_token;
   
    /**
     * Internal token counter.
     * @var int
     */
    protected $_counter = 0;
   
    /**
     * Constructor.
     *
     * @param string $string The string to tokenize.
     * @param string $delims The token delimiters.
     */
    public function __construct($string, $delims)
    {
        $this->_string = $string;
        $this->_delims = $delims;
        $this->_token = strtok($string, $delims);
    }
   
    /**
     * @see Iterator::current()
     */
    public function current()
    {
        return $this->_token;
    }
    /**
     * @see Iterator::key()
     */
    public function key()
    {
        return $this->_counter;
    }
    /**
     * @see Iterator::next()
     */
    public function next()
    {
        $this->_token = strtok($this->_delims);
       
        if ($this->valid()) {
            ++$this->_counter;
        }
    }
    /**
     * @see Iterator::rewind()
     */
    public function rewind()
    {
        $this->_counter = 0;
        $this->_token   = strtok($this->_string, $this->_delims);
    }
    /**
     * @see Iterator::valid()
     */
    public function valid()
    {
        return $this->_token !== FALSE;
    }
}
Пример 7.
$str=str_repeat('foo ',10000);
//explode()
$time=microtime(TRUE);
$arr=explode($str,' ');
$time=microtime(TRUE)-$time;
echo "explode():$time sec.".PHP_EOL;
//strtok()
$time=microtime(TRUE);
$ret=strtok(' ',$str);
while($ret!==FALSE){
    $ret=strtok(' ');
}
$time=microtime(TRUE)-$time;
echo "strtok():$time sec.".PHP_EOL;
Пример 8.
for($tok = strtok($str, ' _-.'); $tok!==false; $tok = strtok(' _-.'))
{
  echo "$tok </br>";
}
Пример 9.
$text = "13 202 5 This is a long message explaining the error codes.";
$error1 = strtok($text, " "); //13
$error2 = strtok(" "); //202
$error3 = strtok(" "); //5
$error_message = strtok(""); //Notice the different token parameter
echo $error_message; //This is a long message explaining the error codes.
Пример 10.
function tokenize($str, $token_symbols) {
    $word = strtok($str, $token_symbols);
    while (false !== $word) {
        // do something here...
        $word = strtok($token_symbols);
    }
}
Пример 11.
$token = strtok($keywords,' ');
while ($token) {
    // find double quoted tokens
    if ($token{0}=='"') { $token .= ' '.strtok('"').'"'; }
    // find single quoted tokens
    if ($token{0}=="'") { $token .= ' '.strtok("'")."'"; }
    $tokens[] = $token;
    $token = strtok(' ');
}
Пример 12.
/**
* The string tokenizer class allows an application to break a string into tokens.
* @example The following is one example of the use of the tokenizer. The code:
*/
    $str = 'this is:@\t\n a test!';
    $delim = ' !@:'\t\n; // remove these chars
    $st = new StringTokenizer($str, $delim);
    while ($st->hasMoreTokens()) {
           echo $st->nextToken() . "\n";
    }
    prints the following output:
      this
      is
      a
      test
Пример 13.
header('Content-type: text/plain; charset=utf-8');
/**
 * NOTE : use mbstring.func_overload for multi-byte support with this function
 *
 * @param string $string             the string to tokenize
 * @param int $offset                the starting offset
 * @param string $defaultTokenName   the default token name if none specified
 * @param string $groupDelimiters    the characters to delimit token groups
 * @param string $groupNameDelimiter the character(s) to delimit token group names
 * @return array
 */
function getTokens(
            $string,
        $offset = 0,
        $defaultTokenName = null,
        $groupDelimiters = '\'"',
        $groupNameDelimiter = ':')
{
        if ($offset >= strlen($string)) {
            //echo "offset out of range";
        return false;
    }
    $spaces = " \t\n\r";   // space characters
    // add group delimiters to spaces...
    $groupSpaces = $spaces . $groupNameDelimiter;
    $delimiters = $groupSpaces . $groupDelimiters;
    //var_dump($groupSpaces);
    $string = ltrim(substr($string, $offset), $groupSpaces);
    $token_strings = array();
    //echo "String is : " . $string . "\n";
    // 1. split all tokens...
    while ($offset < strlen($string)) {
            $lastOffset = $offset;
        $escaped = false;
        if (false !== strpos($groupDelimiters, $char = $string[$offset])) {
                    $groupChar = $char;
        } else {
                    $groupChar = null;
        }
        if (null !== $groupChar) {
                    while (($offset < strlen($string)) && (($groupChar !== ($char = $string[++$offset])) || $escaped)) {
                            //$offset++;
                $escaped = ('\\' === $char);
            }
            $offset++;
            //echo "*** Grouped : " . substr($string, $lastOffset, $offset - $lastOffset) . "\n";
        } else {
                    while (($offset < strlen($string)) && ((false === strpos($delimiters, $char = $string[$offset])) || $escaped)) {
                            $offset++;
                $escaped = ('\\' === $char);
            }
            //echo "*** Non-group : " . substr($string, $lastOffset, $offset - $lastOffset) . "\n";
        }
        //skip spaces...
        while (($offset < strlen($string)) && ((false !== strpos($groupSpaces, $char = $string[$offset])) || $escaped)) {
                    $offset++;
            $escaped = ('\\' === $char);
        }
        $token_strings[] = substr($string, $lastOffset, $offset - $lastOffset);
        //echo "Next token = '" . end($token_strings) . "'\n";
    }
    $tokens = array();
    $tokenName = null;
    foreach ($token_strings as $token_str) {
            // clean $token_str
        $token_str = trim(stripslashes($token_str), $spaces);
        $str_value = trim($token_str, $delimiters);
        switch (strtolower($str_value)) {
                case 'true': $str_value = true; break;
                        case 'false': $str_value = false; break;
                        default: break;
                    }
        // is it a token name?
        if (':' === substr($token_str, -1, 1)) {
                    if (!empty($tokenName)) {
                            $tokens[$tokenName] = '';
            }
            $tokenName = trim($token_str, $delimiters);
        } else {
                    if (!empty($tokenName)) {
                            if (isset($tokens[$tokenName])) {
                                    $tokens[$tokenName] = array(
                                            $tokens[$tokenName],
                        $str_value
                    );
                } else {
                                    $tokens[$tokenName] = $str_value;
                }
                $tokenName = null;
            } elseif (empty($defaultTokenName)) {
                            $tokens[] = trim($token_str, $delimiters);;
            } else {
                            if (isset($tokens[$defaultTokenName])) {
                                    $tokens[$defaultTokenName] = array(
                                            $tokens[$defaultTokenName],
                        $str_value
                    );
                } else {
                                    $tokens[$defaultTokenName] = $str_value;
                }
            }
        }
    }
    if (!empty($tokenName)) {
            $tokens[$tokenName] = '';
    }
    return $tokens;
}
$str = "check1: test "
     . "check2:'hello world' "
     . 'check3: "foo" '
     . "check4: \\\"try this\\\""
     . '"buz" '
     . 'check1:true';
Пример 14.
$selector = 'div.class#id';
$tagname = strtok($selector,'.#');
echo $tagname.'<br/>';
while($tok = strtok('.#'))
{
    echo $tok.'<br/>';
}
Пример 15.
/* subtok(string,chr,pos,len)
*
* chr = chr used to seperate tokens
* pos = starting postion
* len = length, if negative count back from right
*
*  subtok('a.b.c.d.e','.',0)     = 'a.b.c.d.e'
*  subtok('a.b.c.d.e','.',0,2)   = 'a.b'
*  subtok('a.b.c.d.e','.',2,1)   = 'c'
*  subtok('a.b.c.d.e','.',2,-1)  = 'c.d'
*  subtok('a.b.c.d.e','.',-4)    = 'b.c.d.e'
*  subtok('a.b.c.d.e','.',-4,2)  = 'b.c'
*  subtok('a.b.c.d.e','.',-4,-1) = 'b.c.d'
*/
function subtok($string,$chr,$pos,$len = NULL) {
      return implode($chr,array_slice(explode($chr,$string),$pos,$len));
}

Смотрите также split() и explode().

Все функции строки
Описание на ru2.php.net
Описание на php.ru