Цикл через ASCII-коды в пакетном файле
Я хочу эхо от A до Z без ввода for %%J in (ABCDEFGHIJKLMNOPQRSTU VWXYZ) do echo %%J
такими длинными и бесплодными командами. Поэтому мне было интересно, могу ли я перебирать коды ASCII. Что-то похожее for %%J in (ASCII of A ie.65 to Z) do echo %%J
Любая помощь будет оценена по достоинству.
Ответы
Ответ 1
Удивительно, но есть решение, которое использует недокументированную встроенную переменную среды с именем =ExitCodeAscii
, которая содержит символ ASCII текущего кода выхода 1 (ErrorLevel
):
@echo off
for /L %%A in (65,1,90) do (
cmd /C exit %%A
call echo %%^=ExitCodeAscii%%
)
Цикл for/L
проходит через (десятичные) коды символов от A
до Z
cmd/C exit %%A
устанавливает код возврата (ErrorLevel
) в текущий итерированный код, который впоследствии является echo
-ed. call
, вместе с double- %
-signs вводят вторую фазу разбора для командной строки, чтобы получить текущее значение =ExitCodeAscii
а не тот, который присутствует до выполнения всего цикла for/L
(это произойдет с простая командная строка, такая как echo %=ExitCodeAscii%
). В качестве альтернативы можно использовать и замедленное расширение.
Основная идея зачисляется на rojo и применяется в этом сообщении: Как получить произвольную буквенную выгрузку в пакетном режиме.
1) Код выхода (или код возврата) не обязательно совпадает с значением ErrorLevel
.Однако в командной строке cmd/C exit 1
устанавливаются оба значения равными 1
.Чтобы убедиться, что код выхода равен ErrorLevel
, используйте что-то вроде cmd/C exit %ErrorLevel%
.
Ответ 2
Цикл через ASCII-коды в пакетном файле
Любое пакетное решение, чтобы делать то, что вы хотите, было бы намного сложнее, чем то, что у вас уже есть.
Вместо этого используйте PowerShell:
for($i=65;$i -le 90; $i++){[char]$i}
Пример вывода:
PS F:\test> for($i=65;$i -le 90; $i++){[char]$i}
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Ответ 3
Этот ответ представляет собой компиляцию и сравнение методов, приведенных ранее.
В этом вопросе OP запросил отклик от букв от A до Z в пакетном файле. Если цель решения заключается не только в том, чтобы показывать буквы, но и обрабатывать буквы любым другим способом, то метод переменной = ExitCodeAscii является единственным, который делает это с помощью пакетного кода, хотя модификация, требуемая в двух других методах для выполнения такой же простой.
Код ниже включает три метода и сравнивает их самым простым способом: через время, необходимое для завершения каждого из них.
@if (@CodeSection == @Batch) @then
@echo off
setlocal
set "start=%time%"
for /L %%a in (65,1,90) do (
cmd /C exit %%a
call echo Batch: %%^=ExitCodeAscii%%
)
echo First method: using =ExitCodeAscii variable
echo Start: %start%
echo End: %time%
echo/
set "start=%time%"
for /F %%a in ('powershell "65..90 | %%{ [char]$_ }"') do echo PS: %%a
echo Second method: using PowerShell
echo Start: %start%
echo End: %time%
echo/
set "start=%time%"
for /F %%a in ('cscript //nologo //E:JScript "%~F0"') do echo JScript: %%a
echo Third method: using JScript
echo Start: %start%
echo End: %time%
goto :EOF
@end
for (var i=65; i<=90; i++) WSH.Echo(String.fromCharCode(i));
Несколько исполнений этого кода показывают согласованные результаты: метод PowerShell является самым медленным, метод = ExitCodeAscii выполняется на 280% быстрее, чем PowerShell, а метод JScript работает на 240% быстрее, чем = ExitCodeAscii. Эти различия будут уменьшаться по мере роста всей программы и выполнения большего количества вещей, чем просто показывать буквы, но в стандартных/небольших командных файлах это отношение всегда будет одинаковым: PowerShell является самым медленным методом, а JScript - самым быстрым. Метод VBScript похож на JScript.
Ответ 4
В Vbscript вы можете сделать что-то вроде этого:
For i = 65 To 90
Car = Car & Chr(i) & vbTab
Next
wscript.echo Car
И вы можете сгенерировать его с помощью пакетного файла следующим образом:
@echo off
Call :vbs
Pause
exit /b
:vbs
(
echo For i = 65 To 90
echo Car = Car ^& Chr(i^) ^& vbTab
echo Next
echo wscript.echo Car
)>"%tmp%\%~n0.vbs"
Cscript /NoLogo "%tmp%\%~n0.vbs"
Ответ 5
Самое простое решение - включить этот однострочный PowerShell в ваш скрипт bat:
powershell "[char[]](65..90)"
Однако это не обязательно самый быстрый.
Здесь решение VBScript похоже на Hackoo's, но в гибридном формате, не полагаясь на запись внешнего файла.vbs. Сохраните его с расширением.bat. cscript
- это то, что запускает гибридный код VBScript.
<!-- : batch portion
@echo off & setlocal
cscript /nologo "%~f0?.wsf"
goto :EOF
: VBScript -->
<job>
<script language="VBScript">
For i = 65 to 90
WSH.Echo(Chr(i))
Next
</script>
</job>
Или, если вам более удобно с синтаксисом JavaScript, вот гибрид Batch + JScript.
@if (@CodeSection == @Batch) @then
@echo off & setlocal
cscript /nologo /e:JScript "%~f0"
goto :EOF
@end // end Batch / begin JScript
for (var i=65; i<=90; i++) WSH.Echo(String.fromCharCode(i));
Ответ 6
awk обеспечивает функциональность.
asc () { awk -v n=$1 'BEGIN { printf "%c", n }'; }
for n in $(seq 65 90)
do
echo $(asc $n)
done
Если у нас есть оболочка bash, мы могли бы использовать пару команд printf
для преобразования чисел в ascii:
asc () { bash -c "printf '%b\n' $(printf '\\\x%x' $1)"; }
for n in $(seq 65 90)
do
echo $(asc $n)
done
Ответ 7
Эта маленькая жемчужина приходит на ум, поскольку она не обфускается и разумно исполнена:
@set _ASCII=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
@for %%J in (%_ASCII%) do @echo %%J
Отделите данные от логики потока программы и читайте лучше. Время работы под микросекундой в моей системе примерно на порядок выше, чем у других схем.
Единственный тип, который могут выполнять сценарии Windows Batch, - это когда он мгновенно продвигает строки в целое число, а затем снова возвращается к строке.