带有外语字符的 php sprintf() ?

2022-08-30 16:40:50

接缝像冲刺一样,对前额字符有问题吗?还是我做错了什么?看起来当从字符串中删除像åäö这样的字符时,它的工作原理。这有必要吗?

我希望以下行能够正确对齐报表:

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


答案 1

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

有关详细信息,请参阅:
https://www.php.net/manual/en/language.types.string.php#language.types.string.details

PHP中的大多数字符串函数都有多字节等效(带有前缀)。但事实并非如此。mb_sprintf

有一个用户评论(由“viktor at textalk dot com”)在函数的文档页面上的多字节实现 php.net。它可能对你有用:
https://www.php.net/manual/en/function.sprintf.php#89020sprintf


答案 2

我实际上试图找出PHP ^7是否最终有一个原生的,但显然没有xD。mb_sprintf()

为了完整起见,这是我在一些旧项目中一直使用的简单解决方案。它只是将 & 之间的差异添加到所需的 。添加非多字节示例只是为了便于比较 =)。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\n", $text);
printf("%{$mbTargetLength}s\n", $mbText);
printf("%{$mbRussianTargetLength}s\n", $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\n", 'thüs', 'wörks', 'ök');
echo mb_sprintf("%-10s %-10s %10s\n", 'this', 'works', 'ok');

结果

thüs       wörks              ök
this       works              ok

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


推荐