How to through a semicolon separated list in a string

C

Csaba Gabor

I'd like to be able to loop through all the entries in a semicolon
separated list in a single string. How should I do it?

Specifically, I have an sqlite database where one of the fields is
a semicolon separated list of entries. I can easily get the nonempty
fields like so (and boy those line continuation characters (^) are picky):

FOR /F "tokens=1,* delims=:" %%G ^
IN ('c:\sqlite.exe c:\Mydb^
"SELECT Id||':'||myList FROM myTable;"')^
DO @ECHO %%G-^>%%H

But what I really need to be able to do is to loop through that
semicolon separated list in %%H (and stuff each element from
it into another variable, call it %%K). For my purposes it
would probably be sufficient if you could show me how to print
out individually each item in %%H on a separate line.

Thanks,
Csaba Gabor (a batch file newbie)
 
M

Matthias Tacke

:
Hello Csaba,
I'd like to be able to loop through all the entries in a semicolon
separated list in a single string. How should I do it?

Specifically, I have an sqlite database where one of the fields is
a semicolon separated list of entries. I can easily get the nonempty
fields like so (and boy those line continuation characters (^) are picky):

FOR /F "tokens=1,* delims=:" %%G ^
IN ('c:\sqlite.exe c:\Mydb^
"SELECT Id||':'||myList FROM myTable;"')^
DO @ECHO %%G-^>%%H

IMO formatting with breaks at natural points after ( and in front of )
is better readable:

@echo off
FOR /F "tokens=1,* delims=:" %%G IN (
'c:\sqlite.exe c:\Mydb "SELECT Id||':'||myList FROM myTable;"'
) DO ECHO %%G-^>%%H
But what I really need to be able to do is to loop through that
semicolon separated list in %%H (and stuff each element from
it into another variable, call it %%K). For my purposes it
would probably be sufficient if you could show me how to print
out individually each item in %%H on a separate line.

Thanks,
Csaba Gabor (a batch file newbie)
Depending on format and content of the fields you have to prepare the
lines before parsing.
Are the fields quoted, are there empty fields with successing semicolons,
are there semicolons or other difficult to handle chars inside fields?

This batch could work if fields are not quoted.

@echo off & setlocal enableextensions enabledelayedexpansion
FOR /F "tokens=1,* delims=:" %%G IN (
'c:\sqlite.exe c:\Mydb "SELECT Id||':'||myList FROM myTable;"'
) DO (
set line="%%H"
set line2=!line:;=" "!
Call :parse !line2!
)
goto :eof
:parse
IF NOT [%1] EQU [] echo/%~1 & shift & goto :parse
 
C

Csaba Gabor

Hey Matthias, thanks for the nice response, it
was really quite informative. And it has raised
more questions than it answered (I say that in a
good way - please see below)...

Matthias Tacke said:
:
Hello Csaba,


IMO formatting with breaks at natural points after ( and in front of )
is better readable:

@echo off
FOR /F "tokens=1,* delims=:" %%G IN (
'c:\sqlite.exe c:\Mydb "SELECT Id||':'||myList FROM myTable;"'
) DO ECHO %%G-^>%%H

This is good to know, thanks. Can natural and batch be in the
same sentence?
Depending on format and content of the fields you have to prepare the
lines before parsing.
Are the fields quoted, are there empty fields with successing semicolons,
are there semicolons or other difficult to handle chars inside fields?

As to my fields, they are not quoted but they may be NULL.
Turns out that's a good thing, because if myList is NULL,
so is the whole concatenated expression, so the FOR never
sees it. It just sees the lines that have well formed data (with
no ;; either).
This batch could work if fields are not quoted.

@echo off & setlocal enableextensions enabledelayedexpansion
FOR /F "tokens=1,* delims=:" %%G IN (
'c:\sqlite.exe c:\Mydb "SELECT Id||':'||myList FROM myTable;"'
) DO (
set line="%%H"
set line2=!line:;=" "!
Call :parse !line2!
)
goto :eof
:parse
IF NOT [%1] EQU [] echo/%~1 & shift & goto :parse
I reposted because the title of this post is messed up and perhaps
my solution there is simpler, but yours is more educational for me.
In particular, if I read yours correctly, it is more general. The general
idea of what you're doing is clear, but the specifics interest me very
much. Where can I read the documentation about this ! form, which
I haven't seen before (I can't search for that on google, after all). It
seems like you're doing that replace that I'm after, yes? But I'd really
like to understand this exclamation syntax on both the second
set line, and the Call.

Also, what does the slash (/) after the echo and the tilde (~)
accomplish? I read that && is a conditional continuation (only
do the part to the right if the part to the left is not "false". Is
& simply a distinct command separator (which is what unconditional
continuation is)? Actually, if you have a recommended link that
explains these types of language basics, that would be just great.

Thanks, Csaba
 
J

Jim Davis

Csaba said:
Also, what does the slash (/) after the echo and the tilde (~)
accomplish? I read that && is a conditional continuation (only
do the part to the right if the part to the left is not "false". Is
& simply a distinct command separator (which is what unconditional
continuation is)? Actually, if you have a recommended link that
explains these types of language basics, that would be just great.

You quoted the answer to part of this. See below:

Check the index for "&" and explains the difference between & and &&.

Also, "for /?" mentions toward the bottom that %~x is just like %x,
except without quotes around it.

A slash immediately after echo (not after a space!), as far as I can
tell, does nothing special if there are other items being echoed. If
there's nothing else ("echo/"), it prints a blank line.
 
M

Matthias Tacke

Csaba Gabor said:
This is good to know, thanks. Can natural and batch be in the
same sentence?
With "natural" I only meant that you can break lines at that points
without problems. The shells ignores these breaks.

And yes, you may mix with the line continuation symbol ^

I reposted because the title of this post is messed up and perhaps
my solution there is simpler, but yours is more educational for me.
In particular, if I read yours correctly, it is more general. The general
idea of what you're doing is clear, but the specifics interest me very
much. Where can I read the documentation about this ! form, which
I haven't seen before (I can't search for that on google, after all). It
seems like you're doing that replace that I'm after, yes? But I'd really
like to understand this exclamation syntax on both the second
set line, and the Call.
See set /?

The ! instead of a % is for delayed expansion. Normally vars used inside
an area enclosed in parenthes are evaluated by the shell only once. To
force the changed value being used you have to either use tricks with
call's or use delayed expansion (available from w2k on) Delayed expansion
must be explicitly enabled with setlocal.
See setlocal /?

Calls to internal subs must be preceeded with a colon.
See call /?
Also, what does the slash (/) after the echo and the tilde (~)
accomplish?
As Jim already pointed out the / is a valid delimiter I used to avoid
an echo status being displayed when the contents of the var is empty.
see scho /?
I read that && is a conditional continuation (only
do the part to the right if the part to the left is not "false". Is
& simply a distinct command separator (which is what unconditional
continuation is)? Actually, if you have a recommended link that
explains these types of language basics, that would be just great.
As Jim already pointed out, see my signature :)
 
C

Csaba Gabor

Matthias and Jim,

thank you, Thank You, THANK YOU!
Your responses have been incredibly helpful, and I have done
a lot of reading following up the pointers you gave. Exactly what
I was looking for.

This delayed evaluation is very useful, but I ran into a few pitfalls
which I wanted to share by way of example for anyone else happening
on this thread. Evidently, as far as I can make out, the form
SET EnvVar=!oldVar:str1=str2!
introduces a surrounding pair of double quotes around EnvVar.
You can get rid of them by using:
SET EnvVar=!EnvVar:~1,-1!

However, it seems that some component doesn't like this quote stripping
happening inline with output redirection. Thus, consider the following
example:

REM ECHO %* // display the argument line
setlocal ENABLEDELAYEDEXPANSION
FOR %%G IN (%*) DO @(
SET infile="%%~G"
SET outdest=!infile:.cdf=.txt!
REM SET outdest=!outdest:~1,-1!
c:\myProg.exe !infile:~1,-1! > !outdest!
)


If on the final line, we instead put !outdest:~1,-1! the commad
interpreter complains mightily. To remove the quotes, I could
remove the last REMmed line. infile also has a surrounding pair
of quotes, but it seems like I can remove them inline. Just something
to be aware of.

Thanks again,
Csaba Gabor

PS. My comment about natural and batch was meant to be a
humorous comment about the cryptic (to me) syntax of batch files.
 
G

guard

PS. My comment about natural and batch was meant to be a
humorous comment about the cryptic (to me) syntax of batch files.

You may want to look at the %.ForExpand% command, which is less cryptic than
using "!" for delayed expansion and has the added benefit of working under
Windows NT in addition to 2K, XP and Server 2003.

See (http://TheSystemGuard.com/MtCmds/CrystalClear/ForExpand.htm)

*******

The FREE Advanced Command Library provides over 200 resources in a similar
fashion using ONLY builtin commands and utilities.

See (http://ntlib.com).

*******

-tsg

/-----------------+---------------+----------------------\
| COMPATIBILITY | CLARITY | SPEED |
| Write code ONCE | Make it clear | THEN...Make it fast! |
\-----------------+---------------+----------------------/
400+ command-line resources using ONLY native NT commands!
(http://TheSystemGuard.com/default.asp#MasterCommandList)
 
M

Matthias Tacke

:
This delayed evaluation is very useful, but I ran into a few pitfalls
which I wanted to share by way of example for anyone else happening
on this thread. Evidently, as far as I can make out, the form

SET EnvVar=!oldVar:str1=str2!
introduces a surrounding pair of double quotes around EnvVar.

No, that replaces all occurences of str1 with str2
You can get rid of them by using:
SET EnvVar=!EnvVar:~1,-1!

That cuts off the first and the last char independent from conatents.
However, it seems that some component doesn't like this quote stripping
happening inline with output redirection. Thus, consider the following
example:

REM ECHO %* // display the argument line
setlocal ENABLEDELAYEDEXPANSION
FOR %%G IN (%*) DO @(
SET infile="%%~G"
SET outdest=!infile:.cdf=.txt!
REM SET outdest=!outdest:~1,-1!
c:\myProg.exe !infile:~1,-1! > !outdest!
)

If on the final line, we instead put !outdest:~1,-1! the commad
interpreter complains mightily.
According to a test there was no problem with the arguments I used.
To remove the quotes, I could
remove the last REMmed line. infile also has a surrounding pair
of quotes, but it seems like I can remove them inline. Just something
to be aware of.
All the quoting is only neccessary to handle spaces in path or file
names. Your example is very inconsequent in this sense. If a filename
is quoted on the command line and processed in %%G you strip the
eventual quote (which is what the ~ does) put unconditional quotes
around and strip them again, so names with spaces won't work.

Your example task will be better handled this way:
@for %%G in (%*) Do C:\Myprog "%%~fG" >"%%~dpnG.txt"

the %%~fG resulting in the full drive:path\filename.ext
the %%~dpnG being the same without the extension, .txt appended inside
the quotes.

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top