Jefrejtor
Jefrejtor

Reputation: 45

Windows Batch - delayed expansion indexing

I'm writing a batch script that returns logged in users, via the 'query user' command. However, I've encountered a difficulty that other threads here were unable to help me with. Here's my (almost) whole script, only missing some echoes at the end, for brevity:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET me=%~n0
SET parent=%~dp0
SET count=1

FOR /F "skip=1 tokens=* USEBACKQ" %%F IN (`query user`) DO (
    ::obtain line of output
    SET var!count!=%%F 
    ::obtain first character from line
    CALL SET ^faf=^%%var!count!:~0,1%%
    ::testing purposes
    CALL ECHO count:^!count! faf1:^!faf!
     ::remove the '>' character, if present
     IF ^!faf! == ^> ( 
     SET var!count!=!var%count%:~1! && ECHO success )
    SET /a count=!count!+1
)

What it should do is get one of several lines of output, create a temporary variable "faf" that stores the first character from that line, which is then compared to the ">" character, which 'query user' always adds before the current username-if that character is detected, the variable is overwritten, omitting the first character. In the meantinme, the echo prints the current value of loop counter, and the temp variable.
The problem lies in the CALL SET command: it seemingly ignores the line containing the ">" character, for other lines it works as intended. Because of that, the IF never gets used, and echo prints the counter, but not the first character - for the ">" line.
Mind you, the lines are still stored in var1-6, and printing them out with "^" shows that even the line with ">" prints out fine. The only problem is detecting, and omitting, that damned angle bracket. Can anyone help me with this, please? What am I missing?

Upvotes: 0

Views: 105

Answers (2)

sst
sst

Reputation: 1463

I'm not sure why are you doing it the way your are doing it, because you could simply remove > with delims option.

So I assume your intention is to obtain the list of currently logged on users and then use > to identify the current user among those.

If that is the case then you can achieve your goal with something like the code below

Also you should never use :: commenting style inside a parenthesized block. See Which comment style should I use in batch files? for more information regarding that.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET "me=%~n0"
SET "parent=%~dp0"
SET "count=0"

FOR /F "skip=1 tokens=* USEBACKQ" %%F IN (`query user`) DO (

    REM Never use this(::) commenting style inside a parenthesized block
    REM Use REM or use %= This commenting style =% instead
    %= Variable names can not start with equal sign(=) so this can be safely used as a comment =%

    SET /a "count+=1"

    REM obtain line of output
    SET "var!count!=%%F"

    REM obtain first character from line
    FOR %%A IN (!count!) DO SET "faf=!var%%A:~0,1!"

    REM testing purposes
    ECHO count:!count! faf1:!faf!

    REM remove the '>' character, if present
    IF "!faf!"==">" FOR %%A IN (!count!) DO (
        SET "var!count!=!var%%A:~1!"
        ECHO Success

        SET "CurrentUserInfo=!var%%A!"
        SET /a "CurrentUserIndex=count"
        ECHO Current User Info [Inside Loop - By Index]: !var%%A!
        REM Prints a new line
        ECHO, 
    )
)
ECHO,
ECHO Current User Info [Outside Loop - By Index]:   !var%CurrentUserIndex%!
ECHO Current User Info [Outside Loop - By VarName]: %CurrentUserInfo%

ECHO,
ECHO Printing list of all users by index...
FOR /L %%A IN (1,1,!count!) DO ECHO var%%A: !var%%A!
ECHO,
ECHO Current User is stored in var%CurrentUserIndex%


PAUSE

Upvotes: 0

Squashman
Squashman

Reputation: 14290

Remove the > from the output using the DELIMS option of the FOR /F command.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET me=%~n0
SET parent=%~dp0
SET count=1

FOR /F "skip=1 tokens=* USEBACKQ delims=>" %%F IN (`query user`) DO (
    SET var!count!=%%F
    SET /a count+=1
)

Upvotes: 1

Related Questions