Search code examples
batch-fileletter

get letter (X) of (TEXT) in batch


I'm making a password mask in batch, but I need to get a certain letter of a variable for it to work. I am running Windows 7. Here is my code:

@echo off
title Password
set Pass=
set Letters=abcdefghijklmnopqrstuvwxyz

:Loop
cls
echo.
echo Password: %Pass%
choice /c:%Letters% /n
for /l %%a in (1,1,26) do if %errorlevel%==%%a set Pass=%Pass% (Letter %%a of %Letters%)
goto Loop

Solution

  • @ECHO OFF
    SETLOCAL
    REM title Password
    set Pass=
    set Letters=#abcdefghijklmnopqrstuvwxyz0
    
    :Loop
    cls
    echo.
    echo Password: %Pass%
    choice /c:%Letters:~1% /n
    IF ERRORLEVEL 27 GOTO :EOF 
    for /l %%a in (1,1,26) do if %errorlevel%==%%a CALL set Pass=%Pass% %%Letters:~%%a,1%%
    goto Loop
    GOTO :EOF
    

    Here's a how-to in batch.

    The core of the method is CALL set Pass=%Pass% %%Letters:~%%a,1%%

    This is a parsing trick. The argument to call is parsed as

    • set
    • Pass=originalvalueofpassSpace
    • %Letters:~thevalueofawhenmatchwasfound,1%

    So, pressing c would make errorlevel and hence %%a = 3 when matched, so the %letters:~%%a,1% would be %letters:~3,1%

    Using batch substringing. %letters:~3,1% means take the substring of letters, from position 3 for 1 character.

    The substring syntax is

    %var:~start,length% if start >=0 and length >0
    %var:~start,endpos% if start >=0 and endpos <0
    %var:~start,length% if start <0 and length >0
    %var:~start,endpos% if start <0 and endpos <0
    
    • length/endpos may be omitted. If omitted, the substring is "from the start position to the end"
    • % may be ! for delayedexpansion mode

    But here's the difficulty: this substring method starts counting at 0 and we have errorlevel for the letter c = 3. Using substringing, a=0,b=1,c=2,...

    So we cheat by adding an extra character at the beginning of letters. Using this extra character, the letter produced by %letters:~3,1% is c as desired. I chose # - but any character would do.

    Then we restore the errorlevel output from choice by using the substring of letters starting at position 1 (which is the original substring you used.)

    Last little change is that I added an extra character to the end. I chose 0 and it's used as the exit character.

    On entering 0, errorlevel will be 27, so we check for that value explicitly. If a 0 is entered, just exit from the procedure (it can be any label, of course) otherwise, it must be 1..26 so go check the alphabet.