10

How do I loop through ASCII values (here, alphabets) and work on them?

I want to echo A to Z without having to type every character manually like for %%J in (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) do echo %%J

So I was wondering if I can cycle through ASCII codes. Something like for %%J in (ASCII of A ie.65 to Z) do echo %%J

Any help would be appreciated.

Rishav
  • 3,818
  • 1
  • 31
  • 49
  • The only command I know that can translate character codes (ASCII) is `forfiles`, but I'm pretty sure the resulting command line is going to be much longer than your `for` loop, so I suggest to get on with `for`... – aschipfl Jun 23 '16 at 20:34
  • I finally dismissed my idea using `forfiles` because it requires the ASCII given in hex. format and there is no simple way to convert decimal numbers to hex. (I was thinking of looping through the (decimal) codes with a `for /L` loop)... – aschipfl Jun 23 '16 at 22:48
  • 2
    @Sankalp I dont think there is a concept of type casting in Batch fine programming. If you must, ask a new question on SO and consider closing the bounty. Its useless in this case. – Rishav Mar 26 '18 at 08:14
  • You are correct; all variables in batch are strings (except for briefly when you use `set /a` when they get converted to signed 32-bit integers). – SomethingDark Mar 26 '18 at 13:08

5 Answers5

16

Surprisingly, there is a solution that makes use of an undocumented built-in environment variable named =ExitCodeAscii, which holds the ASCII character of the current exit code1 (ErrorLevel):

@echo off
for /L %%A in (65,1,90) do (
    cmd /C exit %%A
    call echo %%^=ExitCodeAscii%%
)

The for /L loop walks through the (decimal) character codes of A to Z. cmd /C exit %%A sets the return code (ErrorLevel) to the currently iterated code, which is echo-ed as a character afterwards. call, together with the double-%-signs introduce a second parsing phase for the command line in order to get the current value of =ExitCodeAscii rather than the one present before the entire for /L loop is executed (this would happen with a simple command line like echo %=ExitCodeAscii%). Alternatively, delayed expansion could be used also.

The basic idea is credited to rojo and applied in this post: How do i get a random letter output in batch.

1) The exit code (or return code) is not necessarily the same thing as the ErrorLevel value. However, the command line cmd /C exit 1 sets both values to 1. To ensure that the exit code equals ErrorLevel, use something like cmd /C exit %ErrorLevel%.

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • The cure seems worse than the disease. Starting an entirely new process for each character in the sequence is not a trivial expenditure. – jwdonahue Mar 29 '18 at 17:36
  • 1
    @jwdonahue, the performance is not the very best, of course, but this is the only simple way in pure batch scripting, without borrowing functions from another language; the question does not specify any details about the implementation, hence this is a valid answer, so no reason for down-voting in my opinion... – aschipfl Mar 29 '18 at 17:40
  • I've seen no stackoverflow documentation that says we can't down-vote for aesthetic reasons and I made it quite clear what those were. – jwdonahue Mar 29 '18 at 20:09
6

Loop through ASCII codes in batch file

Any batch solution to do what you want would be much more complex than what you already have.

Consider using PowerShell instead:

for($i=65;$i -le 90; $i++){[char]$i}

Example output:

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
DavidPostill
  • 7,734
  • 9
  • 41
  • 60
5

This answer is a compilation and comparison of the methods given before.

In the question the OP requested to echo A to Z letters in a batch file. If the purpose of the solution is not just show letters, but process the letters in any other way, then the =ExitCodeAscii variable method is the only one that do that with Batch code, although the modification required in the other two methods to do the same is simple.

The code below include the three methods and compare they in the simplest possible way: via the time required by each one to complete.

@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));

Several executions of this code show consistent results: the PowerShell method is the slowest one, the =ExitCodeAscii method run 280% faster than PowerShell, and JScript method run 240% faster than =ExitCodeAscii. These differences would diminish as the whole program grow and perform more things than just show the letters, but in standard/small Batch files, this relation will always be the same: PowerShell is the slowest method and JScript the fastest one. The VBScript method is similar to JScript.

Aacini
  • 65,180
  • 12
  • 72
  • 108
3

In Vbscript, you can do something like this :

For i = 65 To 90
    Car = Car & Chr(i) & vbTab
Next
wscript.echo Car

And you can generate it with a batch file like this :

@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"
Hackoo
  • 18,337
  • 3
  • 40
  • 70
3

The simplest solution is to include this PowerShell one-liner in your bat script:

powershell "[char[]](65..90)"

It's not necessarily the fastest, though.


Here's a VBScript solution similar to Hackoo's, but in a hybrid format not relying on writing an external .vbs file. Save it with a .bat extension. The cscript line is what triggers execution of the VBScript hybrid code.

<!-- : 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>

Or if you're more comfortable with JavaScript syntax, here's a Batch + JScript hybrid.

@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));
rojo
  • 24,000
  • 5
  • 55
  • 101