Заполнение строки до заданной длины PHP
Думал, форматный вывод строк с заполнением до заданной длины — это занятие для олдфагов, по какой-то причине до сих пор загружающих с дискетки MS DOS на компьютере менее мощном, чем современные электронные наручные часы.
Но в PHP-обработке массивов текста встретился с таким случаем, когда важно видеть все явные и не явные символы текста, да ещё чтобы текстовый массив выглядел приемлемо для понимания.
В общем случае для заполнения строки до заданной длины в PHP достаточно функции printf (sprintf).
Возможности функции для форматного вывода весьма впечатляют, но без бутылки шпаргалки сложно пользоваться функцией (это даже не минус, а просто мнение).
Например, выведем порядковый номер элемента какого-либо списка так, чтобы расстояние справа от него заполнилось пробелами до длины в 10 символов (минус длина номера):
printf( '%-10s', $i );
Не интуитивно, но эффективно. Интересует больше — гуглите. А меня эта функция не устроила тем, что неверно определяет длину строки в «utf-8» (наиболее популярная сейчас кодировка).
Например:
echo sprintf( "%'.-30s", 'шорт' ), "= короткий\n"; echo sprintf( "%'.-30s", 'лоооооооонг' ), "= длинный\n\n";
Ожидается такой результат:
шорт..........................= короткий лоооооооонг...................= длинный
Но результат sprintf не столь прекрасен:
шорт......................= короткий лоооооооонг........= длинный
Дело в том, что кириллические символы utf-8 в «понимании» обычных функций для работы со строками имеют такую длину, как 2 не-кириллических символа (например, знаки пунктуации и латинские символы). Отсюда и ошибки в подсчёте длины строк, и ещё артефакты при резке строк (в виде ромбиков с вопросиками), когда крайний символ режется на 2 части.
Для своих нужд я написал функцию для заполнения строки до заданной длины при выводе:
### ## Строка $t с заполнением справа строкой $s до длины $l ## минимальный размер $l = 3, иначе возвращается $t . $s # function fillstr_utf8( $t, $l, $s = '- ' ) { # sprintf не корректно определяет длину строки в utf-8 if ( $l < 3 ) return $t . $s; $len = mb_strlen( $t, 'utf-8' ); if ( $len >= $l ) { $t = mb_substr( $t, 0, $l - 2, 'utf-8' ) .'…'; $len = $l - 1; } $str = ''; $k = $l - $len; if ( $k ) { while ( mb_strlen( $str, 'utf-8' ) <= $k ) $str .= $s; $t .= mb_substr( $str, -$k, $k, 'utf-8' ); } return $t; }
Эта функция не столь универсальна, как sprintf, зато результат выполнения
echo fillstr_utf8( 'шорт', 30, "." ), "= короткий\n"; echo fillstr_utf8( 'лоооооооонг', 30, "." ), "= длинный\n\n";
выглядит красиво:
шорт..........................= короткий лоооооооонг...................= длинный
А можно даже так:
echo fillstr_utf8( 'шорт', 30, " -:- " ), "= короткий\n"; echo fillstr_utf8( 'лоооооооонг', 30, " -:- " ), "= длинный\n"; echo fillstr_utf8( 'очень длинный текст, который не поместится', 30, " -:- " ), "= overflow hidden\n\n"; /* Результат: шорт -:- -:- -:- -:- -:- = короткий лоооооооонг-:- -:- -:- -:- = длинный очень длинный текст, который… = overflow hidden */
Гет юз!
3 ответа к “Заполнение строки до заданной длины PHP”
Удобная штука. Снова воспользовался описанным выше кодом. По крайней мере, мне самому оказался полезен этот пост.
str_pad?
Да, str_pad в этом случае лучше для примера, чем sprintf. Но, к сожалению, str_pad также не поддерживает мультибайтовые строки (например, кириллица в кодировке utf-8). Длину строки «абвгд» она определяет как 10 символов, а не как 5.