Is it possible to define a delimiter which is not limited to 1 character? Based on the title's example, I would like to define my separator as e.g. '#+#'. Textfiles/lines can contain both characters, but there is very little chance you'll come across that particular substring/text combo.
-
Delimiter for `for`? No, only single chars are possible. Delimiter for `csv`? As far as I know also Excel supports only single character delimiters – Stephan Sep 21 '15 at 08:17
2 Answers
No, you can not use a string as a delimiter in the delims=
clause. Of course you can include the string, but it will be handled as a set of separate characters that will be used as delimiters, not as a delimiter string.
If you really need to split on a string, the fastest approach could be to replace the delimiter string by a character not included in the data and use this character as delimiter
@echo off
setlocal enableextensions disabledelayedexpansion
for /f "delims=" %%a in ("this is a +test!! #+# of string #splitting#") do (
set "buffer=%%a"
setlocal enabledelayedexpansion
(for /f "tokens=1,2 delims=¬" %%b in ("!buffer:#+#=¬!") do (
endlocal
echo full line : [%%a]
echo first token : [%%b]
echo second token : [%%c]
)) || if "!!"=="" endlocal
)
Note: The setlocal enabledelayedexpansion
is needed to be able to read the variable changed inside the for
loop retrieving the data (here simulated directly including a string). Then, inside the for
loop that tokenizes the readed line, delayed expansion is disabled to avoid problems with the !
characters (if delayed expansion is active, they will be consumed by the parser). This is the reason for the endlocal
inside the loop.
As we are doing a string replacement and it is possible to end with a string composed of only delimiters, it is possible that the do
clause of the inner for
will not be executed, so the final if
is included to ensure that the enabledelayedexpansion
is cancelled.

- 69,615
- 8
- 84
- 126
-
...concerning the final `endlocal`: so `for` sets the `ErrorLevel` if its body is never executed? – aschipfl Sep 21 '15 at 20:50
-
@aschipfl, no, it does not *set* the `errorlevel` variable, but in `cmd` most of the commands are coded as functions that will return an exit sucess/failure value, and the conditional execution operator uses this value to determine code execution. If the `for /f` does not iterate over any line, its asociated function will return a failure code but will not set the `errorlevel`. You can find more information about this behaviour in [this question](http://stackoverflow.com/q/30714985/2861476). Read at least the answers (this is the logical order) from dbenham, eryksun and my own answer. – MC ND Sep 22 '15 at 05:52
-
#MC ND: so that's how humility feels like :) That said: way to complicated for myself/ITteam. Done some testing with the ASCII_ANSI, and probably something is these lines: @echo off rem *** ASCII Alt+221 set MyDelim=¦ dir *.* /b >dirlist.txt Setlocal EnableDelayedExpansion set Count=testingValue for /f "tokens=*" %%i in (dirlist.txt) do ( set AddValue=%%i%MyDelim%%Count% echo [!AddValue!] ) pause – Badt_Paul Sep 22 '15 at 08:23
-
@Badt_Paul, Sorry, sure I'm missing something but I don't see the a clear relation between the question (asking how to split the data) and the code in your comment. Is it trying to generate the data that later you will have to split? – MC ND Sep 22 '15 at 08:35
-
The goal is to ensure that the delimiter always works; is unique. Hence a multi_char delimiter would have been the solution. Since this is not possible, the next 'best thing' would be to use a delimiter that is hardly/not-at-all used. I have (can have) control over the delimiter, not its contents. But the generated files are "pure" ASCII (not UTF for the moment). And so to answer your question: I receive the delimited file, which I then need to "split". – Badt_Paul Sep 22 '15 at 08:51
-
Wow, that's weird, @MCND! up to now I thought the conditional execution operators rely on `ErrorLevel`, but that's not the case apparently; thank you for the _very_ ineresting information! – aschipfl Sep 22 '15 at 12:03
I recently discovered an interesting trick that allows to use a multi-character string as delimiter to split a larger string in a very simple way; the method does not use any for
command, but perform the split in just one line! Here it is:
@echo off
set "str=this is a +test!! #+# of string #splitting#"
set "first=%str:#+#=" & set "last=%"
echo full line : [%str%]
echo first token : [%first%]
echo last token : [%last%]
This method also allows to split a large string in several parts and store all of them in an array. Further details at dos batch iterate through a delimited string
-
I was about to ask if this could be extended to multiple (3+) seperated values, but your link shows such example. Did not test it yet, but this is indeed what I've been looking for. (I also confess that I can not explain why this is working...) – Badt_Paul Oct 15 '15 at 16:55
-
@Badt_Paul: If you want to review another example of this method with more explanations, see: http://stackoverflow.com/questions/32578014/how-to-extract-version-number-in-a-windows-batch-file/33112178#33112178 – Aacini Oct 15 '15 at 17:11
-
Strangely, this neat trick doesn't seem to work when you simply place the logic between parenthesis ( set "str= ... echo last :[%last%] ) ... – RKO Mar 13 '20 at 03:00
-
@RKO: Yes, but this is an inherent limitaton of `%variable%` expansion: `( set "var=Not works" & echo %var% )`. You may `EnableDelayedExpansion` and then use `( set "var=Works" & echo !var! )` – Aacini Mar 13 '20 at 17:57