Цикл через 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, - это когда он мгновенно продвигает строки в целое число, а затем снова возвращается к строке.