• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • sprintf()

    (PHP 4, PHP 5, PHP 7)

    返回格式化字符串

    说明

    sprintf(string $format[,mixed $...]): string

    返回根据格式化字符串生成的字符串$format.

    参数

    $format

    The format string is composed of zero or more directives: ordinary characters(excluding%)that are copied directly to the result andconversion specifications, each of which results in fetching its own parameter.

    A conversion specification follows this prototype:%[argnum$][flags][width][.precision]specifier.


    Argnum

    An integer followed by a dollar sign$, to specify which number argument to treat in the conversion.

    Flags
    Flag说明
    -Left-justify within the given field width; Right justification is the default
    +Prefix positive numbers with a plus sign+; Default only negative are prefixed with a negative sign.
    (space)Pads the result with spaces. This is the default.
    0Only left-pads numbers with zeros.Withsspecifiers this can also right-pad with zeros.
    '(char)Pads the result with the character(char).


    Width

    An integer that says how many characters(minimum)this conversion should result in.


    Precision

    A period.followed by an integer who's meaning depends on the specifier:

    • Fore,E,fandFspecifiers: this is the number of digits to be printed after the decimal point(by default, this is 6).
    • ForgandGspecifiers: this is the maximum number of significant digits to be printed.
    • Forsspecifier: it acts as a cutoff point, setting a maximum character limit to the string.
    Note:If the period is specified without an explicit value for precision, 0 is assumed.


    Note:Attempting to use a position specifier greater thanPHP_INT_MAXwill generate warnings.

    Specifiers
    Specifier说明
    %A literal percent character. No argument is required.
    bThe argument is treated as an integer and presented as a binary number.
    cThe argument is treated as an integer and presented as the character with that ASCII.
    dThe argument is treated as an integer and presented as a(signed)decimal number.
    eThe argument is treated as scientific notation(e.g. 1.2e+2). The precision specifier stands for the number of digits after the decimal point since PHP 5.2.1. In earlier versions, it was taken as number of significant digits(one less).
    ELike theespecifier but uses uppercase letter(e.g. 1.2E+2).
    fThe argument is treated as a float and presented as a floating-point number(locale aware).
    FThe argument is treated as a float and presented as a floating-point number(non-locale aware). Available as of PHP 5.0.3.
    g

    General format.

    Let P equal the precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X:

    If P > X ≥−4, the conversion is with style f and precision P −(X + 1). Otherwise, the conversion is with style e and precision P − 1.

    GLike thegspecifier but usesEandF.
    oThe argument is treated as an integer and presented as an octal number.
    sThe argument is treated and presented as a string.
    uThe argument is treated as an integer and presented as an unsigned decimal number.
    xThe argument is treated as an integer and presented as a hexadecimal number(with lowercase letters).
    XThe argument is treated as an integer and presented as a hexadecimal number(with uppercase letters).
    Warning

    Thectype specifier ignores padding and width

    Warning

    Attempting to use a combination of the string and width specifiers with character sets that require more than one byte per character may result in unexpected results

    Variables will be co-erced to a suitable type for the specifier:

    Type Handling
    TypeSpecifiers
    strings
    integerd,u,c,o,x,X,b
    doubleg,G,e,E,f,F

    返回值

    Returns a string produced according to the formatting string$format,或者在失败时返回FALSE.

    范例

    Argument swapping

    The format string supports argument numbering/swapping.

    <?php
    $num = 5;
    $location = 'tree';
    $format = 'There are %d monkeys in the %s';
    echo sprintf($format, $num, $location);
    ?>

    以上例程会输出:

    There are 5 monkeys in the tree
    

    However imagine we are creating a format string in a separate file, commonly because we would like to internationalize it and we rewrite it as:

    <?php
    $format = 'The %s contains %d monkeys';
    echo sprintf($format, $num, $location);
    ?>

    We now have a problem. The order of the placeholders in the format string does not match the order of the arguments in the code. We would like to leave the code as is and simply indicate in the format string which arguments the placeholders refer to. We would write the format string like this instead:

    <?php
    $format = 'The %2$s contains %1$d monkeys';
    echo sprintf($format, $num, $location);
    ?>

    An added benefit is that placeholders can be repeated without adding more arguments in the code.

    <?php
    $format = 'The %2$s contains %1$d monkeys.
               That\'s a nice %2$s full of %1$d monkeys.';
    echo sprintf($format, $num, $location);
    ?>

    When using argument swapping,then$position specifiermust come immediately after the percent sign(%), before any other specifiers, as shown below.

    Specifying padding character

    <?php
    echo sprintf("%'.9d\n", 123);
    echo sprintf("%'.09d\n", 123);
    ?>

    以上例程会输出:

    ......123
    000000123
    

    Position specifier with other specifiers

    <?php
    $format = 'The %2$s contains %1$04d monkeys';
    echo sprintf($format, $num, $location);
    ?>

    以上例程会输出:

    The tree contains 0005 monkeys
    

    Example #4sprintf(): zero-padded integers

    <?php
    $isodate = sprintf("%04d-%02d-%02d", $year, $month, $day);
    ?>

    Example #5sprintf(): formatting currency

    <?php
    $money1 = 68.75;
    $money2 = 54.35;
    $money = $money1 + $money2;
    echo $money;
    echo "\n";
    $formatted = sprintf("%01.2f", $money);
    echo $formatted;
    ?>

    以上例程会输出:

    123.1
    123.10
    

    Example #6sprintf(): scientific notation

    <?php
    $number = 362525200;
    echo sprintf("%.3e", $number);
    ?>

    以上例程会输出:

    3.625e+8
    

    参见

    • printf()输出格式化字符串
    • fprintf()将格式化后的字符串写入到流
    • vprintf()输出格式化字符串
    • vsprintf()返回格式化字符串
    • vfprintf()将格式化字符串写入流
    • sscanf()根据指定格式解析输入的字符
    • fscanf()从文件中格式化输入
    • number_format()以千位分隔符方式格式化一个数字
    • date()格式化一个本地时间/日期
    1. A plus sign ('+') means put a '+' before positive numbers while a minus sign ('-') means left justify. The documentation incorrectly states that they are interchangeable. They produce unique results that can be combined:
    <?php
    echo sprintf (" | %+4d | %+4d | \n",  1, -1);
    echo sprintf (" | %-4d | %-4d | \n",  1, -1);
    echo sprintf (" | %+-4d | %+-4d | \n", 1, -1);
    ?>
    outputs:
     |  +1 |  -1 | 
     | 1   | -1  | 
     | +1  | -1  | 
    2. Padding with a '0' is different than padding with other characters. Zeros will only be added at the front of a number, after any sign. Other characters will be added before the sign, or after the number:
    <?php
    echo sprintf (" | %04d | \n",  -2);
    echo sprintf (" | %':4d | \n", -2);
    echo sprintf (" | %-':4d | \n", -2);
    // Specifying both "-" and "0" creates a conflict with unexpected results:
    echo sprintf (" | %-04d | \n", -2);
    // Padding with other digits behaves like other non-zero characters:
    echo sprintf (" | %-'14d | \n", -2);
    echo sprintf (" | %-'04d | \n", -2);
    ?>
    outputs:
     | -002 | 
     | ::-2 | 
     | -2:: | 
     | -2  | 
     | -211 | 
     | -2  | 
    With printf() and sprintf() functions, escape character is not backslash '\' but rather '%'.
    Ie. to print '%' character you need to escape it with itself:
    <?php
    printf('%%%s%%', 'koko'); #output: '%koko%'
    ?>
    <?php 
    echo sprintf("%+08d", 0). "<Br>";
    echo sprintf("%+07d", 0). "<Br>";
    echo sprintf("%+06d", 0). "<Br>";
    ?>
    Will produce an output
    +0000000
    +000000
    +00000
    There are already some comments on using sprintf to force leading leading zeros but the examples only include integers. I needed leading zeros on floating point numbers and was surprised that it didn't work as expected.
    Example:
    <?php
    sprintf('%02d', 1);
    ?>
    This will result in 01. However, trying the same for a float with precision doesn't work:
    <?php
    sprintf('%02.2f', 1);
    ?>
    Yields 1.00. 
    This threw me a little off. To get the desired result, one needs to add the precision (2) and the length of the decimal seperator "." (1). So the correct pattern would be
    <?php
    sprintf('%05.2f', 1);
    ?>
    Output: 01.00
    Please see http://stackoverflow.com/a/28739819/413531 for a more detailed explanation.
    Here is how to print a floating point number with 16 significant digits regardless of magnitude:
    <?php
      $result = sprintf(sprintf('%%.%dF', max(15 - floor(log10($value)), 0)), $value);
    ?>
    This works more reliably than doing something like sprintf('%.15F', $value) as the latter may cut off significant digits for very small numbers, or prints bogus digits (meaning extra digits beyond what can reliably be represented in a floating point number) for very large numbers.
    I had a nightmare trying to find the two's complement of a 32 bit number.
    I got this from http://www.webmasterworld.com/forum88/13334.htm (credit where credit is due... =P )
    Quote: ...find out the 2's complement of any number, which is -(pow(2, n) - N) where n is the number of bits and N is the number for which to find out its 2's complement.
    This worked magic for me... previously I was trying to use
    sprintf ("%b",$32BitDecimal);
    But it always returned 10000000000000000000000 when the $32BitDecimal value got above 2,000,000,000.
    This -(pow(2, n) - N)
    Worked remarkably well and was very accurate.
    Hope this helps someone fighting with two's complement in PHP.
    Note that when using the argument swapping, you MUST number every argument, otherwise sprintf gets confused. This only happens if you use number arguments first, then switch to a non-numbered, and then back to a numbered one.
    <?php
    $sql = sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
    // Wont work:
    // Sprintf will complain about not enough arguments.
    $sql = sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%3\$s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
    // Will work: note the %3\$s
    ?>
    I couldn't find what should be a WARNING in the documentation above, that if you have more specifiers than variables to match them sprintf returns NOTHING. This fact, IMHO, should also be noted under return values.
    Using argument swapping in sprintf() with gettext: Let's say you've written the following script:
    <?php
    $var = sprintf(gettext("The %2\$s contains %1\$d monkeys"), 2, "cage");
    ?>
    Now you run xgettext in order to generate a .po file. The .po file will then look like this:
    #: file.php:9
    #, ycp-format
    msgid "The %2\\$s contains %1\\$d monkeys"
    msgstr ""
    Notice how an extra backslash has been added by xgettext.
    Once you've translated the string, you must remove all backslashes from the ID string as well as the translation, so the po file will look like this:
    #: file.php:9
    #, ycp-format
    msgid "The %2$s contains %1$d monkeys"
    msgstr "Der er %1$d aber i %2$s"
    Now run msgfmt to generate the .mo file, restart Apache to remove the gettext cache if necessary, and you're off.
    A more complete and working version of mb_sprintf and mb_vsprintf. It should work with any "ASCII preserving" encoding such as UTF-8 and all the ISO-8859 charsets. It handles sign, padding, alignment, width and precision. Argument swapping is not handled.
    <?php
    if (!function_exists('mb_sprintf')) {
     function mb_sprintf($format) {
       $argv = func_get_args() ;
       array_shift($argv) ;
       return mb_vsprintf($format, $argv) ;
     }
    }
    if (!function_exists('mb_vsprintf')) {
     /**
      * Works with all encodings in format and arguments.
      * Supported: Sign, padding, alignment, width and precision.
      * Not supported: Argument swapping.
      */
     function mb_vsprintf($format, $argv, $encoding=null) {
       if (is_null($encoding))
         $encoding = mb_internal_encoding();
       // Use UTF-8 in the format so we can use the u flag in preg_split
       $format = mb_convert_encoding($format, 'UTF-8', $encoding);
       $newformat = ""; // build a new format in UTF-8
       $newargv = array(); // unhandled args in unchanged encoding
       while ($format !== "") {
       
        // Split the format in two parts: $pre and $post by the first %-directive
        // We get also the matched groups
        list ($pre, $sign, $filler, $align, $size, $precision, $type, $post) =
          preg_split("!\%(\+?)('. | [0 ] | )(-?)([1-9][0-9]* | )(\.[1-9][0-9]* | )([%a-zA-Z])!u",
                $format, 2, PREG_SPLIT_DELIM_CAPTURE) ;
        $newformat .= mb_convert_encoding($pre, $encoding, 'UTF-8');
        
        if ($type == '') {
         // didn't match. do nothing. this is the last iteration.
        }
        elseif ($type == '%') {
         // an escaped %
         $newformat .= '%%';
        }
        elseif ($type == 's') {
         $arg = array_shift($argv);
         $arg = mb_convert_encoding($arg, 'UTF-8', $encoding);
         $padding_pre = '';
         $padding_post = '';
         
         // truncate $arg
         if ($precision !== '') {
          $precision = intval(substr($precision,1));
          if ($precision > 0 && mb_strlen($arg,$encoding) > $precision)
           $arg = mb_substr($precision,0,$precision,$encoding);
         }
         
         // define padding
         if ($size > 0) {
          $arglen = mb_strlen($arg, $encoding);
          if ($arglen < $size) {
           if($filler==='')
             $filler = ' ';
           if ($align == '-')
             $padding_post = str_repeat($filler, $size - $arglen);
           else
             $padding_pre = str_repeat($filler, $size - $arglen);
          }
         }
         
         // escape % and pass it forward
         $newformat .= $padding_pre . str_replace('%', '%%', $arg) . $padding_post;
        }
        else {
         // another type, pass forward
         $newformat .= "%$sign$filler$align$size$precision$type";
         $newargv[] = array_shift($argv);
        }
        $format = strval($post);
       }
       // Convert new format back from UTF-8 to the original encoding
       $newformat = mb_convert_encoding($newformat, $encoding, 'UTF-8');
       return vsprintf($newformat, $newargv);
     }
    }
    ?>
    I created this function a while back to save on having to combine mysql_real_escape_string onto all the params passed into a sprintf. it works literally the same as the sprintf other than that it doesn't require you to escape your inputs. Hope its of some use to people
    <?php
    function mressf()
    {
      $args = func_get_args();
      if (count($args) < 2)
        return false;
      $query = array_shift($args);
      $args = array_map('mysql_real_escape_string', $args);
      array_unshift($args, $query);
      $query = call_user_func_array('sprintf', $args);
      return $query;
    }
    ?>
    Regards
    Jay
    Jaygilford.com
    Using sprintf to force leading leading zeros
    foreach (range(1, 10) as $v) {echo "<br>tag_".sprintf("%02d",$v);}
    displays
    tag_01
    tag_02
    tag_03
    .. etc
    Just a reminder for beginners : example 6 'printf("[%10s]\n",  $s);' only works (that is, shows out the spaces) if you put the html '<pre></pre>' tags ( head-scraping time saver ;-).
    If you use the default padding specifier (a space) and then print it to HTML, you will notice that HTML does not display the multiple spaces correctly. This is because any sequence of white-space is treated as a single space.
    To overcome this, I wrote a simple function that replaces all the spaces in the string returned by sprintf() with the character entity reference "&nbsp;" to achieve non-breaking space in strings returned by sprintf()
    <?php
    //Here is the function:
    function sprintf_nbsp() {
      $args = func_get_args();
      return str_replace(' ', '&nbsp;', vsprintf(array_shift($args), array_values($args)));
    }
    //Usage (exactly like sprintf):
    $format = 'The %d monkeys are attacking the [%10s]!';
    $str = sprintf_nbsp($format, 15, 'zoo');
    echo $str;
    ?>
    The above example will output:
    The 15 monkeys are attacking the [    zoo]!
    <?php
    //The variation that prints the string instead of returning it:
    function printf_nbsp() {
      $args = func_get_args();
      echo str_replace(' ', '&nbsp;', vsprintf(array_shift($args), array_values($args)));
    }
    ?>
    Encoding and decoding IP adress to format: 1A2B3C4D (mysql column: char(8) )
    <?php
    function encode_ip($dotquad_ip)
    {
      $ip_sep = explode('.', $dotquad_ip);
      return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
    }
    function decode_ip($int_ip)
    {
      $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
      return hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
    }
    ?>
    If you want to convert a decimal (integer) number into constant length binary number in lets say 9 bits, use this:
    $binary = sprintf('%08b', $number );
    for example: 
    <?php
    $bin = sprintf('%08b',511 );
    echo $bin."\n";
    ?>
    would output 111111111
    And 2 would output 00000010
    I know the leading zeros are useful to me, perhaps they are to someone else too.
    @ henke dot andersson at comhem dot se: Use vprintf()/vsprintf() for that.
    In the examples, is being shown printf, but it should say sprintf, which is the function being explained... just a simple edition mistake.
    $format = 'There are %1$d monkeys in the %s and %s ';
    printf($format, 100, 'Chennai', 'Bangalore'); 
    Expecting to output
    "There are 100 monkeys in the Chennai and bangalore"
    But, this will output 
    "There are 100 monkeys in the 100 and Chennai"
    Because, the second and Third specifiers takes 1rst and 2nd arguments. Because it is not assigned with any arguments.
    If you use argument numbering, then format specifications with the same number get the same argument; this can save repeating the argument in the function call.
    <?php
    $pattern = '%1$s %1$\'#10s %1$s!';
    printf($pattern, "badgers");
    ?>
    To jrust at rustyparts.com, note that if you're using a double-quoted string and *don't* escape the dollar sign with a backslash, $s and $d will be interpreted as variable references. The backslash isn't part of the format specifier itself but you do need to include it when you write the format string (unless you use single quotes).
    And continuing on the same theme of a key-based sprintf...
    I'm roughly (I can see a couple cases where it comes out wierd) copying the syntax of Python's string formatting with a dictionary. The improvement over the several past attempts is that this one still respects all of the formating options, as you can see in my example.
    And the error handling is really crappy (just an echo). I just threw this together so do with it what you will. =]
    <?php
    function sprintf_array($string, $array)
    {
      $keys  = array_keys($array);
      $keysmap = array_flip($keys);
      $values = array_values($array);
      
      while (preg_match('/%\(([a-zA-Z0-9_ -]+)\)/', $string, $m))
      {  
        if (!isset($keysmap[$m[1]]))
        {
          echo "No key $m[1]\n";
          return false;
        }
        
        $string = str_replace($m[0], '%' . ($keysmap[$m[1]] + 1) . '$', $string);
      }
      
      array_unshift($values, $string);
      var_dump($values);
      return call_user_func_array('sprintf', $values);
    }
    echo sprintf_array('4 digit padded number: %(num)04d ', array('num' => 42));
    ?>
    Cheers!
    Here's a clean, working version of functions to allow using named arguments instead of numeric ones. ex: instead of sprintf('%1$s', 'Joe');, we can use sprintf('%name$s', array('name' => 'Joe'));. I've provided 2 different versions: the first uses the php-like syntax (ex: %name$s), while the second uses the python syntax (ex: %(name)s).
    <?php
    /**
     * version of sprintf for cases where named arguments are desired (php syntax)
     *
     * with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
     *
     * with sprintfn: sprintfn('second: %second$s ; first: %first$s', array(
     * 'first' => '1st',
     * 'second'=> '2nd'
     * ));
     *
     * @param string $format sprintf format string, with any number of named arguments
     * @param array $args array of [ 'arg_name' => 'arg value', ... ] replacements to be made
     * @return string | false result of sprintf call, or bool false on error
     */
    function sprintfn ($format, array $args = array()) {
      // map of argument names to their corresponding sprintf numeric argument value
      $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);
      // find the next named argument. each search starts at the end of the previous replacement.
      for ($pos = 0; preg_match('/(?<=%)([a-zA-Z_]\w*)(?=\$)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
        $arg_pos = $match[0][1];
        $arg_len = strlen($match[0][0]);
        $arg_key = $match[1][0];
        // programmer did not supply a value for the named argument found in the format string
        if (! array_key_exists($arg_key, $arg_nums)) {
          user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
          return false;
        }
        // replace the named argument with the corresponding numeric one
        $format = substr_replace($format, $replace = $arg_nums[$arg_key], $arg_pos, $arg_len);
        $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
      }
      return vsprintf($format, array_values($args));
    }
    /**
     * version of sprintf for cases where named arguments are desired (python syntax)
     *
     * with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
     *
     * with sprintfn: sprintfn('second: %(second)s ; first: %(first)s', array(
     * 'first' => '1st',
     * 'second'=> '2nd'
     * ));
     *
     * @param string $format sprintf format string, with any number of named arguments
     * @param array $args array of [ 'arg_name' => 'arg value', ... ] replacements to be made
     * @return string | false result of sprintf call, or bool false on error
     */
    function sprintfn ($format, array $args = array()) {
      // map of argument names to their corresponding sprintf numeric argument value
      $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);
      // find the next named argument. each search starts at the end of the previous replacement.
      for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
        $arg_pos = $match[0][1];
        $arg_len = strlen($match[0][0]);
        $arg_key = $match[1][0];
        // programmer did not supply a value for the named argument found in the format string
        if (! array_key_exists($arg_key, $arg_nums)) {
          user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
          return false;
        }
        // replace the named argument with the corresponding numeric one
        $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
        $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
      }
      return vsprintf($format, array_values($args));
    }
    ?>
    Just to elaborate on downright's point about different meanings for %f, it appears the behavior changed significantly as of 4.3.7, rather than just being different on different platforms. Previously, the width specifier gave the number of characters allowed BEFORE the decimal. Now, the width specifier gives the TOTAL number of characters. (This is in line with the semantics of printf() in other languages.) See bugs #28633 and #29286 for more details.
    Was looking for a assoc way of using sprintf but couldnt find one, probably wasnt looking hard enough so came up with this. Very very simple indeed...
    <?php
    function sprintf2($str='', $vars=array(), $char='%')
    {
      if (!$str) return '';
      if (count($vars) > 0)
      {
        foreach ($vars as $k => $v)
        {
          $str = str_replace($char . $k, $v, $str);
        }
      }
      return $str;
    }
    echo sprintf2('Hello %your_name my name is %my_name! I am %my_age, how old are you? I like %object!', array(
      'your_name' => 'Ben',
      'my_name' => 'Matt',
      'my_age' => '21',
      'object' => 'food'
    ));
    // Hello Ben my name is Matt! I am 21, how old are you? I like food!
    ?>
    Looks nice anyway :)
    An error in my last example:
    $b = sprintf("%30.s", $a);
    will only add enough spaces before $a to pad the spaces + strlen($a) to 30 places.
    My method of centering fixed text in a 72 character width space is:
    $a = "Some string here";
    $lwidth = 36; // 72/2
    $b = sprintf("%".($lwidth + round(strlen($a)/2)).".s", $a);
    When you're using Google translator, you have to 'escape' the 'conversion specifications' by putting <span class="notranslate"></span> around them.
    Like this:
    <?php
    function getGoogleTranslation($sString, $bEscapeParams = true)
    {
      // "escape" sprintf paramerters
      if ($bEscapeParams)
      {
        $sPatern = '/(?:%% | %(?:[0-9]+\$)?[+-]?(?:[ 0] | \'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])/';    
        $sEscapeString = '<span class="notranslate">$0</span>';
        $sString = preg_replace($sPatern, $sEscapeString, $sString);
      }
      // Compose data array (English to Dutch)
      $aData = array(
        'v'      => '1.0',
        'q'      => $sString,
        'langpair'  => 'en | nl',
      );
      // Initialize connection
      $rService = curl_init();
      
      // Connection settings
      curl_setopt($rService, CURLOPT_URL, 'http://ajax.googleapis.com/ajax/services/language/translate');
      curl_setopt($rService, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($rService, CURLOPT_POSTFIELDS, $aData);
      
      // Execute request
      $sResponse = curl_exec($rService);
      // Close connection
      curl_close($rService);
      
      // Extract text from JSON response
      $oResponse = json_decode($sResponse);
      if (isset($oResponse->responseData->translatedText))
      {
        $sTranslation = $oResponse->responseData->translatedText;
      }
      else
      {
        // If some error occured, use the original string
        $sTranslation = $sString;
      }
      
      // Replace "notranslate" tags
      if ($bEscapeParams)
      {
        $sEscapePatern = '/<span class="notranslate">([^<]*)<\/span>/';
        $sTranslation = preg_replace($sEscapePatern, '$1', $sTranslation);
      }
      
      // Return result
      return $sTranslation;
    }
    ?>
    Thanks to MelTraX for defining the RegExp!
    I needed a piece of code similar to the one Matt posted below, on the 10th of March, 2008. However, I wasn't completely satisfied with Matt's code (sorry, Matt! No offense intended!), because
    1) I don't like to initialize variables when it's not really needed, and
    2) it contains two bugs.
    What are the bugs?
    First, Matt's code tests for count($vars) > 0, but if $var == "Hello world!", then count($var) == 1, but the foreach() will crash because $var has to be an array. So instead, my code tests for is_array($var).
    Second, if a key in $vars is a prefix of any of the later keys in the array (like 'object' is the beginning of 'objective') then the str_replace messes things up. This is no big deal if your keys are hard-coded and you can make sure the keys don't interfere, but in my code the keys are variable. So I decided to first sort the array on a decreasing length of the key.
    <?php
    function cmp($a, $b)
    {
      return strlen($b) - strlen($a);
    }
    function sprintf2($str, $vars, $char = '%')
    {
      if(is_array($vars))
      {
        uksort($vars, "cmp");
        foreach($vars as $k => $v)
        {
          $str = str_replace($char . $k, $v, $str);
        }
      }
      return $str;
    }
    echo sprintf2( 'Hello %your_name, my name is %my_name! I am %my_age, how old are you? I like %object and I want to %objective_in_life!'
           , array( 'your_name'     => 'Matt'
              , 'my_name'      => 'Jim'
              , 'my_age'      => 'old'
              , 'object'      => 'women'
              , 'objective_in_life' => 'write code'
              )
           );
    ?>
    If possible, and if you're willing, you can also embed the key fields in the text between percent-signs, rather than prefixing the keys with one. Sorting is no longer necessary, and the execution time is less than half of the code above:
    <?php
    function sprintf3($str, $vars, $char = '%')
    {
      $tmp = array();
      foreach($vars as $k => $v)
      {
        $tmp[$char . $k . $char] = $v;
      }
      return str_replace(array_keys($tmp), array_values($tmp), $str);
    }
    echo sprintf3( 'Hello %your_name%, my name is %my_name%! I am %my_age%, how old are you? I like %object% and I want to %objective_in_life%!'
           , array( 'your_name'     => 'Matt'
              , 'my_name'      => 'Jim'
              , 'my_age'      => 'old'
              , 'object'      => 'women'
              , 'objective_in_life' => 'write code'
              )
           );
    ?>
    If you're willing to embed the keys in the text, you may also be willing to embed the keys themselves in percent signs, thus shaving off another 30% of the execution time:
    <?php
    function sprintf4($str, $vars)
    {
      return str_replace(array_keys($vars), array_values($vars), $str);
    }
    echo sprintf4( 'Hello %your_name%, my name is %my_name%! I am %my_age%, how old are you? I like %object% and I want to %objective_in_life%!'
           , array( '%your_name%'     => 'Matt'
              , '%my_name%'      => 'Jim'
              , '%my_age%'      => 'old'
              , '%object%'      => 'women'
              , '%objective_in_life%' => 'write code'
              )
           );
    ?>
    Of course, by now the sprintf function is no longer something you'd want to write to mum and dad about...
    Note that when using a sign specifier, the number zero is considered positive and a "+" sign will be prepended to it.
    <?php
    printf('%+d', 0); // +0
    ?>
    To add to other notes below about floating point problems, I noted that %f and %F will apparently output a maximum precision of 6 as a default so you have to specify 1.15f (eg) if you need more.
    In my case, the input (from MySQL) was a string with 15 digits of precision that was displayed with 6. Likely what happens is that the rounding occurs in the conversion to a float before it is displayed. Displaying it as 1.15f (or in my case, %s) shows the correct number.
    Be careful if you use the %f modifier to round decimal numbers as it (starting from 4.3.10) will no longer produce a float number if you set certain locales, so you can't accumulate the result. For example:
    setlocale(LC_ALL, 'es_ES');
    echo(sprintf("%.2f", 13.332) + sprintf("%.2f", 14.446))
    gives 27 instead of 27.78, so use %F instead.
    In the last example of Example#6, there is an error regarding the output.
    printf("[%10.10s]\n", $t); // left-justification but with a cutoff of 10 characters
    This outputs right-justified.
    In order to output left-justified:
    printf("[%-10.10s]\n", $t);
    Be cafeful while trying to refactor longer strings with repeated placeholders like 
      sprintf("Hi %s. Your name is %s", $name, $name);
    to use argument numbering:
      sprintf("Hi %1$s. Your name is %1$s", $name);
    This will nuke you at **runtime**, because of `$s` thing being handled as variable. If you got no $s for substitution, notice will be thrown. 
    The solution is to use single quotes to prevent variable substitution in string:
      sprintf('Hi %1$s. Your name is %1$s', $name);
    If you need variable substitution, then you'd need to split your string to keep it in single quotes:
      sprintf("Hi " . '%1$s' . ". Your {$variable} is " . '%1$s', $name);
    The old "monkey" example which helped me a lot has sadly disappeared.
    I'll Re-post it in comment as a memory.
    <?php
    $n = 43951789;
    $u = -43951789;
    $c = 65; // ASCII 65 is 'A'
    // notice the double %%, this prints a literal '%' character
    printf("%%b = '%b'\n", $n); // binary representation
    printf("%%c = '%c'\n", $c); // print the ascii character, same as chr() function
    printf("%%d = '%d'\n", $n); // standard integer representation
    printf("%%e = '%e'\n", $n); // scientific notation
    printf("%%u = '%u'\n", $n); // unsigned integer representation of a positive integer
    printf("%%u = '%u'\n", $u); // unsigned integer representation of a negative integer
    printf("%%f = '%f'\n", $n); // floating point representation
    printf("%%o = '%o'\n", $n); // octal representation
    printf("%%s = '%s'\n", $n); // string representation
    printf("%%x = '%x'\n", $n); // hexadecimal representation (lower-case)
    printf("%%X = '%X'\n", $n); // hexadecimal representation (upper-case)
    printf("%%+d = '%+d'\n", $n); // sign specifier on a positive integer
    printf("%%+d = '%+d'\n", $u); // sign specifier on a negative integer
    /*
    %b = '10100111101010011010101101'
    %c = 'A'
    %d = '43951789'
    %e = '4.395179e+7'
    %u = '43951789'
    %u = '18446744073665599827'
    %f = '43951789.000000'
    %o = '247523255'
    %s = '43951789'
    %x = '29ea6ad'
    %X = '29EA6AD'
    %+d = '+43951789'
    %+d = '-43951789'
    */
    $s = 'monkey';
    $t = 'many monkeys';
    printf("[%s]\n",   $s); // standard string output
    printf("[%10s]\n",  $s); // right-justification with spaces
    printf("[%-10s]\n",  $s); // left-justification with spaces
    printf("[%010s]\n",  $s); // zero-padding works on strings too
    printf("[%'#10s]\n", $s); // use the custom padding character '#'
    printf("[%10.10s]\n", $t); // left-justification but with a cutoff of 10 characters
    /*
    [monkey]
    [  monkey]
    [monkey  ]
    [0000monkey]
    [####monkey]
    [many monke]
    */
    ?>
    Just wanted to add that to get the remaining text from the string, you need to add the following as a variable in your scanf
    %[ -~]
    Example:
    sscanf($sql, "[%d,%d]%[ -~]", $sheet_id, $column, $remaining_sql);
    Fix for sprintfn function for named arguments (http://php.net/manual/en/function.sprintf.php#94608):
    Change the first line from:
     $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);
    to:
     $arg_nums = array_keys($args);
     array_unshift($arg_nums, 0);
     $arg_nums = array_flip(array_slice($arg_nums, 1, NULL, true));
    php printf and sprintf not seems to support star "*" formatting.
    here is an example:
    printf("%*d\n",3,5);
    this will print just "d" instead of "<two spaces>5"
    I have written a wrapper for sprintf. Add a new %S (upper case s) where the number indicates the number of characters and not bytes.
    This is useful for formatting utf-8 strings.
    <?php
    function SacSprintf( $format) {
        $argv = func_get_args() ;
        array_shift($argv) ;
        $offset = 0; 
        $i = 0; 
        while( preg_match("^A%[+-]*[.]*([0-9.]*)([a-z])^Ai", $format, $match, PREG_OFFSET_CAPTURE, $offset)) {
            if( $match[2][0] == 'S') {
                if( $match[1][0] != '') {
                    $t1 = explode('.', $match[1][0]);
                    $t1[0] = intval($t1[0]) + strlen($argv[$i]) - strlen(utf8_decode($argv[$i]));
                    $l1 = strlen($match[1][0]);
                    $t2 = implode('.', $t1);
                    $l2 = strlen($t2) - $l1; 
                    $format = substr_replace( $format, $t2, $match[1][1], strlen($match[1][0]));
                    $offset += $l2; 
                    $match[2][1] += $l2; 
                }  
                $format[$match[2][1]] = 's'; 
            }  
            $offset += $match[2][1];
            $i++;
        }  
        return vsprintf($format, $argv) ;
    }
    echo "<pre>\n";
    echo "   1234567890123456789012345678901234567890\n";
    echo sprintf("Hola, %-20s is my name\n", "José Luis jiménez");
    echo SacSprintf("Hola, %-20S is my name\n", "José Luis jiménez");
    echo "</pre>\n";
    ?>
    The output will be:
       1234567890123456789012345678901234567890
    Hola, José Luis jiménez is my name
    Hola, José Luis jiménez  is my name
    There is a minor issue in a code of mb_vsprintf function from viktor at textalk dot com.
    In "truncate $arg" section the following line:
     $arg = mb_substr($precision,0,$precision,$encoding);
    needs to be replaced with:
     $arg = mb_substr($arg,0,$precision,$encoding);
    Here is an example how alignment, padding and precision specifier can be used to print formatted list of items:
    <?php
    $out = "The Books\n";
    $books = array("Book 1", "Book 2", "Book 3");
    $pages = array("123 pages ", "234 pages", "345 pages");
    for ($i = 0; $i < count($books); $i++) {
      $out .= sprintf("%'.-20s%'.7.4s\n", $books[$i], $pages[$i]);
    }
    echo $out;
    // Outputs:
    // 
    // The Books
    // Book 1.................123 
    // Book 2.................234 
    // Book 3.................345 
    ?>
    /**
    This function returns a formated string with the legnth you specify
    @string holds the string which you want to format
    @len holds the length you want to format 
    **/
    function formatString($string, $len)
    {
      if (strlen($string) < $len)
      {
        $addchar=($len - strlen($string)) ;
        for ($i = 0; $i < $addchar; $i++) 
        {
          $string=sprintf("$string%s", "0");
        }
      }
      
      if (strlen($string) > $len)
      {
        $string=substr($string,0,$len);
      }
      
      return $string;  
    }

    上篇:soundex()

    下篇:sscanf()