改进了PHP的sprintf

时间:2012-01-19 01:55:48

标签: php python printf

有没有人知道在 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!

我想我自己很容易构建这个,但是如果你知道我的意思,我不想重新发明轮子......但我找不到(也许是错误的搜索关键词)任何地方的任何痕迹。

如果有人可以提供帮助,我感激不尽。

干杯,

5 个答案:

答案 0 :(得分:8)

您可以使用位置(但未命名)参数来执行此操作,例如

printf('Hello %1$s. Your %1$s has just been created!', 'world'); 

请注意:您必须使用单个引号,否则美元符号将导致PHP尝试将$s替换为此变量的值(不存在)

如果你想要命名参数,那么你必须使用正则表达式;例如,请参阅How to replace placeholders with actual values?

答案 1 :(得分:5)

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

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

您可以在占位符n$之后立即使用%,其中n是参数位置(因此%1$s指的是第一个参数(作为字符串) ,%2$s指的是第二个,等等。如上所示,当您使用位置限制的占位符时,您可以在字符串中重复它们,而无需在调用sprintf时重复参数。

答案 2 :(得分:3)

以下代码是从a post by Salathe on 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);

以上两个表达式是等效的,并且都将输出

  

“昨天,我看到了一只猫。它是一只毛茸茸的猫!我从来没有见过一只非常蓬松的猫。”

答案 3 :(得分:2)

我在另一篇文章中回答了这个问题:vsprintf or sprintf with named arguments, or simple template parsing in PHP

但这与您正在寻找的格式相同!

这真是去imho的最佳方式。没有神秘的人物,只需使用密钥名称!

取自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

答案 4 :(得分: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!"

也允许多维数组值。希望能有所帮助。