12.02.2013, 00:47. Показов 23862. Ответов 0
Вывод текста без переноса на новую строку
Авторы: amel27, alexii
Как известно, команда «echo», используемая в пакетных файлах для вывода текста, добавляет символы 0x0D, 0x0A (Carriage Return и Line Feed). Чтобы избежать этого, обычно используют какую-либо внешнюю утилиту, эмулирующую вывод и не добавляющую перенос на новую строку. Однако существует способ добиться такого поведения, используя только встроенные средства командного процессора (обратите внимание на пробелы в конце команд!):
| Bash |
1
2
3
4
5
| @echo off
<nul set /p strTemp=Весь этот текст
<nul set /p strTemp=будет находиться
<nul set /p strTemp=на одной строке. |
|
| Code |
1
| Весь этот текст будет находиться на одной строке. |
|
То есть, мы используем ввод с устройства «nul» в команде «set /p» для эмуляции команды «echo».
Если нужна новая строка, следует, после использования вышеуказанного метода, использовать команду «echo.»:
| Bash |
1
2
3
4
5
6
7
8
| @echo off
<nul set /p strTemp=Весь этот текст
<nul set /p strTemp=будет находиться
<nul set /p strTemp=на одной строке.
echo.
echo А этот - уже на следующей. |
|
| Code |
1
2
| Весь этот текст будет находиться на одной строке.
А этот - уже на следующей. |
|
Содержимое использованной переменной окружения «strTemp» при этом не изменяется:
| Bash |
1
2
3
4
5
6
7
8
9
10
11
| @echo off
set StrTemp=Некое Значение
echo Before: strTemp=[%strTemp%].
<nul set /p strTemp=Весь этот текст
<nul set /p strTemp=будет находиться
<nul set /p strTemp=на одной строке.
echo.
echo After: strTemp=[%strTemp%]. |
|
| Code |
1
2
3
| Before: strTemp=[Некое Значение].
Весь этот текст будет находиться на одной строке.
After: strTemp=[Некое Значение]. |
|
Данный метод можно оформить, например, в виде внутренней процедуры (EchoWithoutCrLf), что делает его нагляднее за счёт использования кавычек:
| Bash |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| @echo off
call :EchoWithoutCrLf "Весь этот текст "
call :EchoWithoutCrLf "будет находиться "
call :EchoWithoutCrLf "на одной строке."
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура EchoWithoutCrLf
rem
rem %1 : текст для вывода.
rem ==========================================================================
:EchoWithoutCrLf
<nul set /p strTemp=%~1
exit /b 0
rem ========================================================================== |
|
| Code |
1
| Весь этот текст будет находиться на одной строке. |
|
Используя требуемое количество символов BackSpace (0x08) при выводе текста, и аналогичное количество символов Space (0x20) и BackSpace (0x08) после вывода текста, можно получить вывод поверх предыдущего текста. Как это выглядит:
1) выводится некий текст длины S символов + S символов BackSpace (для того, чтобы вернуть курсор на начало строки);
2) делается пауза для демонстрации выведенного текста;
3) выводится S символов пробелов (чтобы гарантированно затереть ранее выведенный текст) + S символов BackSpace (для того, чтобы опять вернуть курсор на начало строки).
Здесь важно помнить, что если длина текста превысит ширину окна консоли, то текст будет автоматически перенесён на следующую строку, и вернуть курсор в первоначальную позицию, без сторонних средств, не удастся.
1. Использование команды «set /p»:
| Bash |
1
2
3
4
5
6
7
8
9
| @echo off
<nul set /p strTemp=Можно делать вывод
pause > nul
<nul set /p strTemp=
<nul set /p strTemp=и поверх предыдущего текста.
pause > nul
<nul set /p strTemp= |
|
2. Использование процедуры «EchoWithoutCrLf»:
| Bash |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| @echo off
call :EchoWithoutCrLf "Можно делать вывод"
pause > nul
call :EchoWithoutCrLf " "
call :EchoWithoutCrLf "и поверх предыдущего текста."
pause > nul
call :EchoWithoutCrLf " "
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура EchoWithoutCrLf
rem
rem %1 : текст для вывода.
rem ==========================================================================
:EchoWithoutCrLf
<nul set /p strTemp=%~1
exit /b 0
rem ========================================================================== |
|
Чтобы не рассчитывать потребное количество BackSpace'ов и Space'ов вручную, подобный вывод также можно оформить в виде процедуры, точнее, пары основных процедур (процедура «EchoOut» выводит текст, процедура «EchoClear» «стирает» его) и нескольких вспомогательных («FillBackSpace», «FillSpace», «FillString» и «StrLen», см. комментарии в коде; в процедурах используется методика CMD/BAT: возврат значений из процедур через параметры). Вызывайте их с одной и той же строкой в качестве параметра (в процедуре «EchoClear» переданная строка используется только для подсчёта длины). Таким образом, например, можно эмулировать команду «pause» без переноса курсора на новую строку после вывода текста «Для продолжения нажмите любую клавишу . . .». Также, чтобы каждый раз не дублировать один и тот же текст при вызове процедур «EchoOut»/«EchoClear», можно использовать переменную окружения:
| Bash |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| @echo off
set strText="Конечно, Ваш редактор должен позволять вводить символ BackSpace (0x08)."
call :EchoOut %strText%
pause > nul
call :EchoClear %strText%
set strText="Например, редактор Far Manager'а сие позволяет, используйте Ctrl-Q, Ctrl-H."
call :EchoOut %strText%
pause > nul
call :EchoClear %strText%
rem Эмулируем команду PAUSE без переноса на новую строку
set strText="Нажмите любую клавишу для продолжения..."
call :EchoOut %strText%
pause > nul
call :EchoClear %strText%
echo Продолжаем вывод в той же строке...
exit /b 0
rem ==========================================================================
rem ========================================================================== |
|
Вернёмся немного назад, а именно к:
| Code |
1
| Здесь важно помнить, что если длина текста превысит ширину окна консоли, то текст будет автоматически перенесён на следующую строку, и вернуть курсор в первоначальную позицию, без сторонних средств, не удастся. |
|
Одним из вариантов может быть принудительное ограничение длины выводимого текста шириной окна консоли. Для этого добавим ещё одну вспомогательную процедуру «GetConsoleWidth», которая будет возвращать ширину окна консоли (на самом деле будем возвращать, как нам требуется, на единицу меньше), и немного изменим процедуры «EchoOut»/«EchoClear»:
| Bash |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
| @echo off
set strText="Естественно, если длина выведенного текста превысит (ширина окна консоли командного процессора - 1) символов, произойдёт автоматический перенос текста на следующую строку. В этом нет отличий от команды ECHO."
call :EchoOut %strText%
pause > nul
call :EchoClear %strText%
set strText="Чтобы этого не произошло, ограничим длину выводимого текста рамками ширины окна консоли команлного процессора, то есть, обрежем этот текст."
call :EchoOut %strText%
pause > nul
call :EchoClear %strText%
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура EchoOut
rem
rem %1 : текст для вывода.
rem ==========================================================================
:EchoOut
setlocal enableextensions enabledelayedexpansion
set strText=%~1
rem ---- Получаем строку, заполненную символами BackSpace (0x08) в переменную strBackSpace
call :FillBackSpace "%strText%" strBackSpace
call :GetConsoleWidth intCols
<nul set /p strTemp=!strText:~0,%intCols%!%strBackSpace%
endlocal
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура EchoClear
rem
rem %1 : текст для очистки; используется только для получения длины строки.
rem ==========================================================================
:EchoClear
setlocal enableextensions enabledelayedexpansion
rem ---- Получаем строку, заполненную символами Space (0x20) в переменную strSpace
call :FillSpace "%~1" strSpace
rem ---- Получаем строку, заполненную символами BackSpace (0x08) в переменную strBackSpace
call :FillBackSpace "%~1" strBackSpace
call :GetConsoleWidth intCols
<nul set /p strTemp=!strSpace:~0,%intCols%!!strBackSpace:~0,%intCols%!
endlocal
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура FillBackSpace
rem
rem %1 : строка текста; используется только для получения длины строки.
rem %2 : имя переменной для возврата строки, заполненной символами BackSpace (0x08)
rem ==========================================================================
:FillBackSpace
setlocal enableextensions enabledelayedexpansion
rem ---- Получаем длину переданной строки в переменную intStrLen ---------
call :StrLen "%~1" intStrLen
rem ---- Получаем строку, заполненную символами BackSpace (0x08) в переменную strTempString
call :FillString "" %intStrLen% strTempString
endlocal & set %~2=%strTempString%
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура FillSpace
rem
rem %1 : строка текста; используется только для получения длины строки.
rem %2 : имя переменной для возврата строки, заполненной символами Space (0x20)
rem ==========================================================================
:FillSpace
setlocal enableextensions enabledelayedexpansion
rem ---- Получаем длину переданной строки в переменную intStrLen ---------
call :StrLen "%~1" intStrLen
rem ---- Получаем строку, заполненную символами Space (0x20) в переменную strTempString
call :FillString " " %intStrLen% strTempString
endlocal & set %~2=%strTempString%
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура FillString
rem
rem %1 : символ или строка текста
rem %2 : число повторов
rem %3 : имя переменной для возврата строки, заполненной %2 раз символами %1
rem ==========================================================================
:FillString
setlocal enableextensions enabledelayedexpansion
set strTempString=
for /l %%i in (1,1,%~2) do (
set strTempString=!strTempString!%~1
)
endlocal & set %~3=%strTempString%
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура StrLen
rem
rem %1 : строка текста
rem %2 : имя переменной для возврата длины строки
rem ==========================================================================
:StrLen
setlocal enableextensions enabledelayedexpansion
set strString=%~1
set /a intStrLen = 0
if "!strString!" neq "" (
for /l %%i in (0,1,1024) do (
set strTempString=!strString:~%%i,1!
rem echo strTempString=[%strTempString%]
if [!strTempString!] neq [] (
set /a intStrLen+=1
)
)
)
endlocal & set /a %~2=%intStrLen%
exit /b 0
rem ==========================================================================
rem ==========================================================================
rem Процедура GetConsoleWidth
rem
rem %1 : имя переменной для возврата (ширина окна консоли - 1)
rem ==========================================================================
:GetConsoleWidth
setlocal enableextensions enabledelayedexpansion
rem ---- Получаем (ширина окна консоли - 1) ------------------------------
for /f "tokens=2" %%i in ('start /wait /b mode con: ^| find.exe /i "Столбцы"') do set /a intCols=%%i - 1
endlocal & set /a %~1=%intCols%
exit /b 0
rem ========================================================================== |
|