For /F - Tokens has me puzzled

Microsoft Windows
Post Reply
Simon_Weel
Posts: 36
Joined: 2021-Dec-13, 3:53 pm

For /F - Tokens has me puzzled

Post by Simon_Weel »

I have a script that sets up an new users Outlook profile. Like copying signature file. I have to manually change the names used in the signature file, so I thought I could have done this automagically. Found an excellent tool to find / replace text, so that part is done.
Now I have to extract the users full name to put in the signature file. Which seemed pretty easy:

Code: Select all

net user %username% /domain | findstr /C:"full name" /i
This results in "Full Name <lots of spaces> Simon Weel". To pick up just the name, I use this:

Code: Select all

for /f "tokens=3*" %%G in ('net user %username% /domain ^| findstr /C:"full name" /i') do echo %%G
Thinking the 'tokens=3*' would give me the full name, but it doesn't - it presents my first name only.
Reading the part on For /F it says "Each token specified will cause a corresponding parameter letter to be allocated." I thought the * would assign the whole line to a single variable, and when tried, like 'tokens=*', it does echo the complete line. But if I specify 'tokens=3*' it only returns the third token. Now if I modify the line to:

Code: Select all

for /f "tokens=3*" %%G in ('net user %username% /domain ^| findstr /C:"full name" /i') do echo %%G %%H %%I %%J
it _does_ echo my full name, but followed by %I %J. So apparently, adding the asterisk does not mean it will assign the nth token + the rest of the line to a single variable.

As a work-around, I made some changes and added an extra line to extract the full name:

Code: Select all

for /f "tokens=*" %%G in ('net user %username% /domain ^| findstr /C:"full name" /i') do set name=%%G
SET _result=%name:~41%
ECHO %_result% 
It works, but it's not very elegant. Any thoughts?
OJBakker
Posts: 13
Joined: 2021-Jul-29, 7:06 am

Re: For /F - Tokens has me puzzled

Post by OJBakker »

From the for/f page:

tokens=* will cause all items on each line to be processed.
tokens=3* will process the third token and the 4th + all subsequent items, this can also be written as tokens=3,*
Each token specified will cause a corresponding parameter letter to be allocated. The letters used for tokens are case sensitive.

The following variants will work.

Code: Select all

for /f "tokens=3,*" %%G in ('net user %username% /domain ^| findstr /C:"full name" /i') do set "name=%%G %%H"

for /f "tokens=2,*" %%G in ('net user %username% /domain ^| findstr /C:"full name" /i') do set "name=%%H"
I have added a comma in the tokens, so it is more clear that the * is a separate token.
The 2,* variant is my preferred variant because it returns the entire name as one parameter..
The 3.* variant will return name with 1 trailing space if the entire name is just one parameter (in that case %%H will be empty)..
Simon_Weel
Posts: 36
Joined: 2021-Dec-13, 3:53 pm

Re: For /F - Tokens has me puzzled

Post by Simon_Weel »

I had to chew on it for a while and then the penny dropped! Thanks!
My line of thinking was: 3* selects token 3 and the rest. Wrong! The 3 selects token 3 and assigns it to the specified variable and then * selects token 4 + the rest and assigns it to the next variable.....
User avatar
Simon Sheppard
Posts: 191
Joined: 2021-Jul-10, 7:46 pm
Contact:

Re: For /F - Tokens has me puzzled

Post by Simon Sheppard »

OJBakker wrote: 2023-Aug-02, 1:41 pm From the for/f page:

tokens=* will cause all items on each line to be processed.
tokens=3* will process the third token and the 4th + all subsequent items, this can also be written as tokens=3,*
Each token specified will cause a corresponding parameter letter to be allocated. The letters used for tokens are case sensitive.
I just reworded that page yesterday to make this a bit clearer, the new text is:

tokens=*   Will cause all items on each line to be processed as a single string Token.
tokens=3*  Will process the third item as one string token and then all subsequent text as a second string Token.
This can also be written as tokens=3,*
Each token specified will cause a corresponding parameter letter to be allocated. The letters used for tokens are case sensitive.
OJBakker
Posts: 13
Joined: 2021-Jul-29, 7:06 am

Re: For /F - Tokens has me puzzled

Post by OJBakker »

Nice, may I suggest a few additions / changes?

If an asterix is used in the token = string then it must be the last character in the string.
If the last character in the tokens= string is an asterisk, then one additional parameter is added for all the remaining text on the line.
The parameter added by the asterix is based on the whole tokens = string and not on the number preceding the asterix.

example:

Code: Select all

for /f "tokens=5,4,3,2,1*" %A in ("a b c d e f g") do echo %A_%B_%C_%D_%E_%F_%G
Result: a_b_c_d_e_f g_%G
User avatar
Simon Sheppard
Posts: 191
Joined: 2021-Jul-10, 7:46 pm
Contact:

Re: For /F - Tokens has me puzzled

Post by Simon Sheppard »

OJBakker wrote: 2023-Aug-03, 4:08 pm Nice, may I suggest a few additions / changes?
Thanks I'd never really considered listing the tokens in descending order.

A slightly modified version of your example

Code: Select all

@echo off
for /f "tokens=3,2,1,*" %%A in ("alpha beta gamma delta epsilon") do echo A:%%A  B:%%B  C:%%C  D:%%D
Output:
A:alpha B:beta C:gamma D:delta epsilon
OJBakker
Posts: 13
Joined: 2021-Jul-29, 7:06 am

Re: For /F - Tokens has me puzzled

Post by OJBakker »

:)
The order can be ascending, descending or random, but that is not really important.
The reason I used descending so it is clear the asterix and the token it creates is not related to the last token-number before the asterix in the string.
In testscript I often use the form of echo [%%A] [%%B] [%%C], so empty tokens, space tokens and leading/trailing space in tokens are visible.
But I had to change this because to forumsoftware changed the results because it saw tags like [b], so I switched the script to underscores.
I just noticed I could have disabled BBCode and posted my script with brackets.
Yours version is better than underscores. :)
Post Reply