Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Unexpected FOR /F result

59 views
Skip to first unread message

jgq...@gmail.com

unread,
May 21, 2016, 2:51:06 AM5/21/16
to
Consider the following batch file:

@echo off
for /f "tokens=1,2* delims=:. " %%x in ('ipconfig') do (
if "%%x %%y"=="IPv4 Address" echo %%z)
echo.
for /f "tokens=1-3 delims=:. " %%x in ('ipconfig') do (
if "%%x %%y"=="IPv4 Address" echo %%z)

In the first FOR command I get 192.168.1.234 for %%z whereas surely the result should be just 192, like for the second FOR command, since the full stops/periods should have been removed by "tokens=:. " ?

Am I missing something, or is this a FOR /F anomaly?

foxidrive

unread,
May 21, 2016, 12:38:22 PM5/21/16
to
On 21/05/2016 16:51, jgq...@gmail.com wrote:
> Consider the following batch file:
>
> @echo off
> for /f "tokens=1,2* delims=:. " %%x in ('ipconfig') do (
> if "%%x %%y"=="IPv4 Address" echo %%z)

> In the first FOR command I get 192.168.1.234 for %%z whereas surely the result should be just 192, like for the second FOR command, since the full stops/periods should have been removed by "tokens=:. " ?

The "delims=:. " does split the string up as you said, but the tokens you
have selected don't take the actual makeup of the string into account.


Without seeing the line you are parsing it's hard to give you exact advice.
The ipconfig output changed a little in different Windows versions.


jgq...@gmail.com

unread,
May 21, 2016, 12:47:28 PM5/21/16
to
Here is one of the lines in question - a hex editor shows nothing unusual.

IPv4 Address. . . . . . . . . . . : 192.168.1.232

foxidrive

unread,
May 21, 2016, 2:43:33 PM5/21/16
to
Your code works fine with that string.

@echo off
for /f "tokens=1,2* delims=:. " %%x in (
"IPv4 Address. . . . . . . . . . . : 192.168.1.232"
) do echo if "%%x %%y"=="IPv4 Address" echo "%%z"



jgq...@gmail.com

unread,
May 21, 2016, 3:02:49 PM5/21/16
to
When you say "it works fine with that sting" I get as output (having removed the first ECHO)
"192.168.1.232"
rather than the
"192"
which I was expecting. Windows 7 Pro 64-bit.

foxidrive

unread,
May 21, 2016, 3:12:28 PM5/21/16
to
Yes, that's right. The first echo shows you exactly what is happening in
the line.

Use "ipconfig /all >file.txt" and look at the line ending in a hex viewer.



ipconfig output has CRCRLF


foxidrive

unread,
May 21, 2016, 3:19:47 PM5/21/16
to
On 22/05/2016 05:12, foxidrive wrote:

>>> Your code works fine with that string.
>>>
>>> @echo off
>>> for /f "tokens=1,2* delims=:. " %%x in (
>>> "IPv4 Address. . . . . . . . . . . : 192.168.1.232"
>>> ) do echo if "%%x %%y"=="IPv4 Address" echo "%%z"
>>
>> When you say "it works fine with that sting" I get as output (having removed the first ECHO)
>> "192.168.1.232"
>> rather than the
>> "192"
>> which I was expecting. Windows 7 Pro 64-bit.
>
>
> Yes, that's right. The first echo shows you exactly what is happening in
> the line.
>
> Use "ipconfig /all >file.txt" and look at the line ending in a hex viewer.
>
>
>
> ipconfig output has CRCRLF

I've mislead you there - I tried this code here in Win 7 pro 32 bit and it
shows what you expected. The entire IP address is shown.


@echo off
for /f "tokens=1,2* delims=:. " %%x in ('ipconfig') do (
echo if "%%x %%y"=="IPv4 Address" echo "%%z")
pause



foxidrive

unread,
May 21, 2016, 3:22:24 PM5/21/16
to
On 22/05/2016 02:47, jgq...@gmail.com wrote:
I'm not firing on all cylinders, sorry.

I had your question back to front after I replied the first time - test
this code and you'll see that the tokens need that extra number.



@echo off
for /f "tokens=1,2,3,* delims=:. " %%x in ('ipconfig') do (
echo if "%%x %%y"=="IPv4 Address" echo "%%z")
pause


jgq...@gmail.com

unread,
May 21, 2016, 3:51:15 PM5/21/16
to
I'm now fairly baffled. Here is my extended batch file, having changed to the more usual %%a, %%b, etc, with comments showing what I get:

@echo off
echo 1. next FOR gives "192.168.1.nnn"
for /f "tokens=1,2* delims=:. " %%a in ('ipconfig') do (
if "%%a %%b"=="IPv4 Address" echo "%%c")
echo.
echo 2. next FOR gives "192"
for /f "tokens=1-3 delims=:. " %%a in ('ipconfig') do (
if "%%a %%b"=="IPv4 Address" echo "%%c")
echo.
echo 3. next FOR gives "192.168.1.nnn"
for /f "tokens=1-6 delims=:. " %%a in ('ipconfig') do (
if "%%a %%b"=="IPv4 Address" echo "%%c.%%d.%%e.%%f")
echo.
echo 4. next FOR gives "192"
for /f "tokens=1,2,3,* delims=:. " %%a in ('ipconfig') do (
if "%%a %%b"=="IPv4 Address" echo "%%c")
echo.
echo 5. next FOR gives "192"
for /f "tokens=1,2,3* delims=:. " %%a in ('ipconfig') do (
if "%%a %%b"=="IPv4 Address" echo "%%c")
pause

Do you get the same?

Zaidy036

unread,
May 21, 2016, 4:13:36 PM5/21/16
to
> echo if "%%x %%y"=="IPv4 Address" echo "%%")
> pause
>
try this:
@echo off
for /f "tokens=1,3* delims=:. " %%x in ('ipconfig') do (
echo if "%%x %%y"=="IPv4 Address" echo "%%y")
pause

jgq...@gmail.com

unread,
May 21, 2016, 4:19:10 PM5/21/16
to
It produces nothing, I'm afraid, even if I remove the first ECHO and change the final %%y to %%z.

JJ

unread,
May 22, 2016, 12:59:44 AM5/22/16
to
You're just a victim for the poorly written FOR help.
What you're missing are probably these.

- Adjacent delimiter characters are treated as one token separator.

- Delimiter at start of a line is not treated as a separator.
e.g. in the line " abc def", the first token is "abc".

- The term token for the FOR command refers to the parsed data in the source
line that is to be assigned to the environment variables, not the variables.
i.e. the numbers refers to the index of the parsed data, not the variable
indexes.

- "tokens=1*" is actually "tokens=1,*". "1*" isn't treated as one and the
rest, but one then the rest. i.e. 2 separate tokens.

- The "*" token wildcard will treat any delimiter as data. So any delimiter
characters at the end of a line will be included in the variable.

- "tokens=1-2" means the first and second data are included in the variable
assignment. i.e. "1-3" is same as "1,2,3".

For example, assume we have this incomplete command line:

for /f "tokens=1,3-4,6* delimiters=." %a in ("ab.cd...ef.gh.ij.kl.mn.op")

- Token#1 is "ab" and is assigned to %a
- Token#2 is "ef" and is assigned to %b
- Token#3 is "gh" and is assigned to %c
- Token#4 is "kl" and is assigned to %d
- Token#5 is "mn.op." and is assigned to %e

So since "tokens=1,3-4,6*" is "tokens=1,3-4,6,*".
Treat it like this: (1),(3-4),(6),(*)
Then like this: (1=%a), (3=%b, 4=%c), (6=%d), (*=%e)

I hope that isn't confusing.

JJ

unread,
May 22, 2016, 1:03:24 AM5/22/16
to
On Sun, 22 May 2016 11:59:42 +0700, JJ wrote:
>
> - Delimiter at start of a line is not treated as a separator.
> e.g. in the line " abc def", the first token is "abc".

I meant, the delimiter character(s) at start of a line will be removed from
the entire process. As if they don't exist.

Sorry.

foxidrive

unread,
May 22, 2016, 1:38:56 AM5/22/16
to
On 22/05/2016 05:51, jgq...@gmail.com wrote:
>>
>> I had your question back to front after I replied the first time - test
>> this code and you'll see that the tokens need that extra number.
>>
>>
>>
>> @echo off
>> for /f "tokens=1,2,3,* delims=:. " %%x in ('ipconfig') do (
>> echo if "%%x %%y"=="IPv4 Address" echo "%%z")
>> pause
>
> I'm now fairly baffled. Here is my extended batch file, having changed to the more usual %%a, %%b, etc, with comments showing what I get:

It helps to give English descriptions and exact situations to solve the
problem.


> Do you get the same?

I'm not sure what you are trying to solve.


jgq...@gmail.com

unread,
May 22, 2016, 2:16:31 AM5/22/16
to
I refer you to the first post. I am attempting to determine why

for /f "tokens=1,2* delims=:. " %%x in ('ipconfig') do (
if "%%x %%y"=="IPv4 Address" echo %%z)

produces 192.168.1.234 for %%z and not just 192, which I would regard as incorrect.

I will have to read JJ's explanation later today...


foxidrive

unread,
May 22, 2016, 2:33:43 AM5/22/16
to
You need to add the third token.



This is what you are seeing:

IPv4 Address. . . . . . . . . . . : 192.168.1.232
1 2 *


=======================================================

And this is what you want. Note the token number 3.


IPv4 Address. . . . . . . . . . . : 192.168.1.232
1 2 3 *



jgq...@gmail.com

unread,
May 22, 2016, 7:51:47 AM5/22/16
to
The question seems to boil down to whether or not the '*', 'the rest', token should be subject to "delims=" processing, or not.
I have always thought that it should be...

Petr Laznovsky

unread,
May 26, 2016, 12:49:20 PM5/26/16
to
Dne 21.5.2016 v 8:51 jgq...@gmail.com napsal(a):
Dealing with 'ipconfig' output parsing some time a go, decided this is too unreliable to get IP
address of network interface. Firts issue is the ipconfig output is language dependent, second is it
does not display statically assigned IP address if cable is unplugged or wifi is disconnected. After
spent some time by experiments I decided to parse WMI query output rather.

L.

Zaidy036

unread,
May 26, 2016, 1:56:39 PM5/26/16
to
Try this:
FOR /f "tokens=8 delims=<>" %%A in ('"C:\Program Files
(x86)\GnuWin32\bin\wget.exe" -O- -q http://checkip.dyndns.org') DO SET
"_IPA=%%A"
ECHO %_IPA:~19,3%

Petr Laznovsky

unread,
May 26, 2016, 3:20:13 PM5/26/16
to
Dne 26.5.2016 v 19:56 Zaidy036 napsal(a):
First: Me (and believe jgq...@gmail.com too) talking about IP address assignet to network interface,
regardless to possible NAT on the way from computer to the internet, but you are show way, how to
get public IP.

Second: If you want to get public IP, use simply way:

for /f %%a in ('curl -s http://icanhazip.com') do echo %%a

L.

Tom Del Rosso

unread,
May 28, 2016, 2:36:29 AM5/28/16
to
Are you sure it has CR/LF at the end of the line, or do they appear in
unequal numbers like CR/LF/LF?

That is the case in some versions, and it definitely confuses FOR.

If so, pipe the output through FIND which will clean up the codes.

for /f "tokens=1,2* delims=:. " %%x in ('ipconfig ^| find /i "IPv4
Address"') do (
if /i "%%x %%y"=="IPv4 Address" echo %%z)


foxidrive

unread,
May 28, 2016, 4:05:01 AM5/28/16
to
On 28/05/2016 16:36, Tom Del Rosso wrote:
> Are you sure it has CR/LF at the end of the line, or do they appear in
> unequal numbers like CR/LF/LF?
>
> That is the case in some versions, and it definitely confuses FOR.
>
> If so, pipe the output through FIND which will clean up the codes.

Find doesn't do that here - tested in XP where that problem is evident.

This is after filtering through find.

000000: 20 20 20 20-20 20 20 20-49 50 20 41-64 64 72 65 IP Addre
000010: 73 73 2E 20-2E 20 2E 20-2E 20 2E 20-2E 20 2E 20 ss. . . . . . .
000020: 2E 20 2E 20-2E 20 2E 20-2E 20 3A 20-31 39 32 2E . . . . . : 192.
000030: 31 36 38 2E-30 2E 31 32-0D 0D 0A - 168.0.12♪♪◙


There's a solution using an extra loop that was devised on Dostips forum,
which handles the wrong line endings.


Tom Del Rosso

unread,
May 28, 2016, 11:48:02 AM5/28/16
to
foxidrive wrote:
> On 28/05/2016 16:36, Tom Del Rosso wrote:
>> Are you sure it has CR/LF at the end of the line, or do they appear
>> in unequal numbers like CR/LF/LF?
>>
>> That is the case in some versions, and it definitely confuses FOR.
>>
>> If so, pipe the output through FIND which will clean up the codes.
>
> Find doesn't do that here - tested in XP where that problem is
> evident.
> This is after filtering through find.
>
> 000000: 20 20 20 20-20 20 20 20-49 50 20 41-64 64 72 65 IP
> Addre 000010: 73 73 2E 20-2E 20 2E 20-2E 20 2E 20-2E 20 2E 20 ss. .
> . . . . . 000020: 2E 20 2E 20-2E 20 2E 20-2E 20 3A 20-31 39 32 2E .
> . . . . : 192. 000030: 31 36 38 2E-30 2E 31 32-0D 0D 0A -
> 168.0.12???
>
> There's a solution using an extra loop that was devised on Dostips
> forum, which handles the wrong line endings.

Yeah I've used that method. But this is weird because FIND also seemed
to fix the problem with FOR when I experienced it, so if it didn't fix
the CRLF then I don't know why it fixed the problem.


Tom Del Rosso

unread,
May 28, 2016, 12:03:08 PM5/28/16
to
foxidrive wrote:
> On 28/05/2016 16:36, Tom Del Rosso wrote:
>> Are you sure it has CR/LF at the end of the line, or do they appear
>> in unequal numbers like CR/LF/LF?
>>
>> That is the case in some versions, and it definitely confuses FOR.
>>
>> If so, pipe the output through FIND which will clean up the codes.
>
> Find doesn't do that here - tested in XP where that problem is
> evident.
> This is after filtering through find.
>
> 000000: 20 20 20 20-20 20 20 20-49 50 20 41-64 64 72 65 IP
> Addre 000010: 73 73 2E 20-2E 20 2E 20-2E 20 2E 20-2E 20 2E 20 ss. .
> . . . . . 000020: 2E 20 2E 20-2E 20 2E 20-2E 20 3A 20-31 39 32 2E .
> . . . . : 192. 000030: 31 36 38 2E-30 2E 31 32-0D 0D 0A -
> 168.0.12???
>
> There's a solution using an extra loop that was devised on Dostips
> forum, which handles the wrong line endings.

This is how I did it with DOS (and Windows that ran under DOS):

N FIXCRLF.COM
A100
;
;0100
;CHECK INPUT BUFFER
;
MOV AH,0B ;see if end of data
INT 21
OR AL,AL
JZ 0185 ;exit if no more data
MOV BYTE [0198], FF ;flag at least 1 char was received
;
;
MOV AH, 08 ;input char to AL (08 allows ctrl-break)
INT 21
;
;
CMP AL, 0D ;CR
JE 0123
;
CMP AL, 0A ;LF
JE 012F
;
CMP AL, 0C ;FF
JE 0135
;
CMP AL, 20 ;SPC
JE 0138
;
JMP 013E ;other char
;
;
;0123 CR
;
INC WORD [0199] ;inc CR count
MOV WORD [019D], 00 ;reset SPC count
JMP 0100
;
;
;012F LF
;
INC WORD [019B] ;inc LF count
;MOV WORD [019D], 00 ;reset SPC count
JMP 0100
;
;
;0135 FF
;
PUSH AX ;save char
JMP 016B ;output FF char
;
;
;0138 SPC
;
INC WORD [019D] ;inc SPC count
JMP 0100
;
;
;013E OTHER CHAR
;
PUSH AX ;save char
;
MOV CX, [0199]
CMP CX, [019B] ;compare CR to LF
JA 014D
MOV CX, [019B] ;if CR lower, use LF for loop count
;
;014D
;
JCXZ 015D ;if no CR or LF, skip
;
;014F OUTPUT CR-LF PAIRS
;
MOV DL, 0D ;output CR
MOV AH, 02
INT 21
;
MOV DL, 0A ;output LF
MOV AH, 02
INT 21
;
LOOP 014F
;
;
;015D
;
MOV CX, [019D] ;use SPC count
;
JCXZ 016B ;if no SPC, skip
;
;0163 OUTPUT SPACES
;
MOV DL, 20 ;output SPC
MOV AH, 02
INT 21
;
LOOP 0163
;
;
;016B
;
POP DX ;output last char received
MOV AH, 02
INT 21
;
MOV WORD [0199], 00 ;reset CR count
MOV WORD [019B], 00 ;reset LF count
MOV WORD [019D], 00 ;reset SPC count
;
;
JMP 0100
;
;
;
;0185 PRINT MESSAGE
;
CMP BYTE [0198], 0
JNZ 0193
MOV DX,19F
MOV AH,09
INT 21
;
;0193 EXIT
;
MOV AX, 4C00
INT 21
;
;
;
;0198 DATA RECEIVED FLAG
DB 00
;
;0199 CR (0D) COUNT
DW 0000
;
;019B LF (0A) COUNT
DW 0000
;
;019D SPC (20) COUNT
DW 0000
;
;
;
;019F
;
DB D A ' CR/LF filter
DB D A '
DB D A 'Replaces CR/LF codes that are not paired properly with CR/LF
pairs.
DB D A 'Also removes trailing spaces from each line, and CR or LF at
EOF.
DB D A '
DB D A 'Written by Thomas Del Rosso 12/98
DB D A '$


RCX
0176
W
Q


Zaidy036

unread,
May 28, 2016, 12:20:45 PM5/28/16
to
sorry but I do not have curl installed. A less elegant approach:

--- sub your drive for "f"
ipconfig > f:\ip.txt
FINDSTR "IPv4" f:\ip.txt > f:\ipx.txt
SET /P _IP= < f:\ipx.txt
SET _IP=%_IP:~39,3%
DEL f:\ip?.txt



0 new messages