php sprintf()与外国字符?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php sprintf()与外国字符?相关的知识,希望对你有一定的参考价值。

像sprintf一样的接缝有外国字符的问题吗?还是我做错了什么?看起来它在从字符串中移除像åäö这样的字符时起作用了。这有必要吗?

我希望为报告正确对齐以下行:

2011-11-27   A1823    -Ref. Leif  -           12 873,00    18.98
2011-11-30   A1856    -Rättat xx -            6 594,00    19.18

我正在使用这样的sprintf():% - 12s% - 8s - % - 10s - %20s%8.2f

使用:php-5.3.23-nts-Win32-VC9-x86

答案

PHP中的字符串基本上是字节数组(不是字符)。它们不能使用多字节编码(例如UTF-8)本地工作。

详情见: https://www.php.net/manual/en/language.types.string.php#language.types.string.details

PHP中的大多数字符串函数都具有多字节等效(使用mb_前缀)。但sprintf没有。

在php.net的函数文档页面上有一个用户评论(由“webmaster at cafe-clope dot net”)和sprintf的多字节实现。它可能适合你: https://www.php.net/manual/en/function.sprintf.php#55837

另一答案

我实际上试图找出PHP ^ 7最终是否有本机mb_sprintf()但显然没有xD。

为了完整起见,这是一个我在一些旧项目中使用的简单解决方案。它只是将strlenmb_strlen之间的差异添加到所需的$targetLengh。为了便于比较,添加了非多字节示例=)。

$text = "Gultigkeitsprufung ist fehlgeschlagen: %{errors}";
$mbText = "Gültigkeitsprüfung ist fehlgeschlagen: %{errors}";
$mbTextRussian = "Проверка не удалась: %{errors}";

$targetLength = 60;
$mbTargetLength = strlen($mbText) - mb_strlen($mbText) + $targetLength;
$mbRussianTargetLength = strlen($mbTextRussian) - mb_strlen($mbTextRussian) + $targetLength;

printf("%{$targetLength}s
", $text);
printf("%{$mbTargetLength}s
", $mbText);
printf("%{$mbRussianTargetLength}s
", $mbTextRussian);

结果

            Gultigkeitsprufung ist fehlgeschlagen: %{errors}
            Gültigkeitsprüfung ist fehlgeschlagen: %{errors}
                              Проверка не удалась: %{errors}

更新2019-06-12


@flowtron让我再想一想。一个简单的mb_sprintf()可能看起来像这样。

function mb_sprintf($format, ...$args) {
    $params = $args;

    $callback = function ($length) use (&$params) {
        $value = array_shift($params);
        return strlen($value) - mb_strlen($value) + $length[0];
    };

    $format = preg_replace_callback('/(?<=%|%-)d+(?=s)/', $callback, $format);

    return sprintf($format, ...$args);
}

echo mb_sprintf("%-10s %-10s %10s
", 'thüs', 'wörks', 'ök');
echo mb_sprintf("%-10s %-10s %10s
", 'this', 'works', 'ok');

结果

thüs       wörks              ök
this       works              ok

我在这里只做了一些快乐的路径测试,但它适用于PHP> = 5.6,并且应该足以让ppl了解如何封装行为。但它不适用于重复/顺序修饰符 - 例如%1$20s将被忽略/保持不变。

另一答案

如果您使用的是符合ISO-8859-1字符集的字符,则可以在格式化之前转换字符串,并在完成后将结果转换回UTF8

utf8_encode(sprintf("%-12s %-8s", utf8_decode($paramOne), utf8_decode($paramTwo))

以上是关于php sprintf()与外国字符?的主要内容,如果未能解决你的问题,请参考以下文章

PHP中变量扩展与sprintf的性能

PHP 格式化字符串sprintf()

php sprintf()

sprintf格式化字符串带来的注入隐患

带有动态字符串的 sprintf()

很早的一部外国电影片段音乐有骑白马在大海边有海浪声和海鸥鸣叫