PHP的sprintf函数有什么改进?

4

有没有人知道在PHP中更好的sprintf实现方式?我正在寻找类似于Python中的字符串格式化方法:

print "Hello %(name)s. Your %(name)s has just been created!" % { 'name' : 'world' }
# prints::: Hello world. Your world has just been created!

这很方便,可以避免不必要的重复使用变量,例如:

sprintf("Hello %s. Your %s has just been created!", 'world', 'world');
# prints::: Hello world. Your world has just been created!

我猜自己建立这个东西应该不难,但是我不想重复造轮子,如果你知道我的意思...但是我找不到任何关于这个的痕迹(也许是搜索关键词错误)。

如果有人能帮忙,我感激不尽。

干杯,


1
如果您想使用MySQL的_INSERT ... ON DUPLICATE KEY UPDATE语法构建广泛的查询,这将具有特别有趣的用途... http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html - bruno.braga
请参考以下链接:https://dev59.com/jG025IYBdhLWcg3w9quQ 和 https://dev59.com/0Gs05IYBdhLWcg3wIOXS。 - lqez
5个回答

8
你可以使用位置参数(但不是命名参数)来完成此操作,例如:
printf('Hello %1$s. Your %1$s has just been created!', 'world'); 

这里需要注意:必须使用单引号,否则美元符号会导致PHP尝试用该变量的值(该变量不存在)替换$s

如果你想要命名参数,则必须使用正则表达式来实现;例如,请参见如何使用实际值替换占位符?


5

您可以使用 PHP 的 sprintf 重复相同的占位符(尽管可能看起来不太好看):

$str = sprintf('%1$s %1$s', 'yay');
// str: 'yay yay'

你可以在占位符中的百分号后面使用n$,其中n是参数位置(例如,%1$s表示第一个参数(作为字符串),%2$s表示第二个参数,等等)。从上面你可以看到,当你使用位置相关的占位符时,你可以在字符串内重复使用它们而不必在调用sprintf时重复参数。

你说得对...虽然不太好看,但至少能解决问题。谢谢! - bruno.braga

3
以下代码是从Salathe在TalkPHP上的一篇帖子中盗取的。
$szAdjective = 'fluffy';
$szNoun = 'cat';

printf('Yesterday, I saw a %s. '.
       'It was a %s %s! I have '.
       'never seen a %s quite so %s.',
       $szNoun,
       $szAdjective,
       $szNoun,
       $szNoun,
       $szAdjective);

printf('Yesterday, I saw a %1$s. '.
       'It was a %2$s %1$s! I have '.
       'never seen a %1$s quite so %2$s.',
       $szNoun,
       $szAdjective);

上述两个表达式是等价的,它们都会输出:

"昨天,我看到了一只猫。它是一只毛茸茸的猫!我从未见过如此毛茸茸的猫。"


2
我在另一篇文章中回答了这个问题:vsprintf或sprintf与命名参数或简单模板解析在PHP中。但是它具有您要查找的相同格式!我认为这真的是最好的方法。没有神秘的字符,只需使用键名即可!正如来自php网站的内容所示:http://www.php.net/manual/en/function.vsprintf.php
function dsprintf() {
  $data = func_get_args(); // get all the arguments
  $string = array_shift($data); // the string is the first one
  if (is_array(func_get_arg(1))) { // if the second one is an array, use that
    $data = func_get_arg(1);
  }
  $used_keys = array();
  // get the matches, and feed them to our function
  $string = preg_replace('/\%\((.*?)\)(.)/e',
    'dsprintfMatch(\'$1\',\'$2\',\$data,$used_keys)',$string);
  $data = array_diff_key($data,$used_keys); // diff the data with the used_keys
  return vsprintf($string,$data); // yeah!
}

function dsprintfMatch($m1,$m2,&$data,&$used_keys) {
  if (isset($data[$m1])) { // if the key is there
    $str = $data[$m1];
    $used_keys[$m1] = $m1; // dont unset it, it can be used multiple times
    return sprintf("%".$m2,$str); // sprintf the string, so %s, or %d works like it should
  } else {
    return "%".$m2; // else, return a regular %s, or %d or whatever is used
  }
}

$str = <<<HITHERE
Hello, %(firstName)s, I know your favorite PDA is the %(pda)s. You must have bought %(amount)s
HITHERE;

$dataArray = array(
  'pda'         => 'Newton 2100',
  'firstName'   => 'Steve',
  'amount'      => '200'
);
echo dsprintf($str, $dataArray);
// Hello, Steve, I know your favorite PDA is the Newton 2100. You must have bought 200

不错,谢谢分享!我宁愿使用这个,而不是你提到的“晦涩难懂”的东西。 - bruno.braga

0

我写了一个小组件,可以让你在 PHP 字符串中进行名称替换。它被称为 StringTemplate。 使用它,你可以通过以下代码获得想要的结果:

$engine = new StringTemplate\Engine;

$engine->render(
   '"Hello {name}. Your {name} has just been created!"',
   [
      'name' => 'world',
   ]
);
//Prints "Hello world. Your world has just been created!"

多维数组值也是允许的。希望这可以帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接