Тема: CMD/BAT: повторить строку несколько раз
Самая простая реализация алгоритма - (N - 1) раз склеить исходную строку с самой собой, чтобы получить новую строку содержащую N копий исходной (сложность алгоритма - O(n) = n). Однако этот алгоритм простой и неоптимальный с точки зрения скорости выполнения, существует более оптимальный, хотя и чуть более сложный алгоритм. Суть его -- удвоение строки. То есть сложность алгоритма порядка O(n) = log2(n). Давайте рассмотрим его подробнее:
Дано:
S - строка
N - умножитель, то есть сколько раз строку S повторить в результирующей строке// Только непустые строки и не менее одного раза
if N <= 0 or S == ''
return ''
end if// Инициализация -- вычисление длины исходной строки
R = S
K = strlen(R)// Инициализация -- счетчики
L = 1
N = N - 1// Повторять пока счетчик не обнулится
while N <= 0
// Остаток -- найти оставшуюся подстроку, добавить к результирующей и завершить
if N <= L then
M = N * K
Q = substr(R, -M)
R = R + Q
break
end if// Удвоение строки
N = N - L
R = R + R
end whilereturn R
Хотя язык и средства обработки строк не дотягивают до возможностей полноценного языка высокого уровня, тем не менее я озадачился -- а можно ли в пакетных скриптах реализовать этот алгоритм. Оказывается можно. Хотя возникла небольшая сложность, но и она была преодолена. Необходимое замечание - я не видел, чтобы этот алгоритм был часто востребован в пакетных скриптах, меня больше интересовала сама возможность реализации. Если кому-то это может пригодиться, я буду рад.
CMD/BAT: Repeat a string multiple times
:: Повторить MULTIPLIER раз строку INPUT
::
:: @usage call :str_repeat NAME MULTIPLIER INPUT
::
:: @param name имя переменной для сохранения результата
:: @param number количество раз
:: @param string входная строка
:str_repeat
setlocal enabledelayedexpansion
set R=
set N=
set /a N=%~2 2>nul
if not defined N goto str_repeat_break
if %N% leq 0 goto str_repeat_break
set R=%~3
if not defined R goto str_repeat_break
call :str_len K "%R%"
set /a L=1
set /a N=%N%-1
:str_repeat_continue
if %N% leq 0 goto str_repeat_break
if %N% leq %L% (
set /a M=%N% * %K%
call :str_repeat_part
set R=%R%!Q!
goto str_repeat_break
)
set /a N=%N% - %L%
set R=%R%%R%
set /a L*=2
goto str_repeat_continue
:str_repeat_break
endlocal && set %~1=%R%
exit /b 0
:str_repeat_part
set Q=!R:~-%M%!
goto :EOF