Splitting a multi-line environment variable into lines
I have the following problem:
I execute a windows batch file on a Jenkins server and have to split a multi-line environment variable (set vía a Jenkins parameter) into single lines. Each line is part of a parameter list for another program:
Jenkins textbox parameter:
- Git on Windows, “Out of memory - malloc failed”
- Jenkins can not clone Git repository over Git/SSH on Windows
- How can Windows file and folder shortcuts be created via C#.NET code?
- Git for Windows: .bashrc or equivalent config files for Git Bash shell
- How to fix windows line endings after git clone
- Git: rename directory (case-only) on Windows
-foo 224 -bar "Some parameter with spaces" -foo 225 -bar "another param"
Should lead to the following calls inside Jenkins:
myprog.exe -baz 0 -meow -foo 224 -bar "Some parameter with spaces" myprog.exe -baz 0 -meow -foo 225 -bar "another param"
I tried to split it with
for /F but did not have any success. Searching did not turn up anything useful, anything I tried gave me syntax errors or just printed the first line.
This is among the things that I tried:
for /f "tokens=* delims= " %%f in ("%varname%") do
Gives me syntax errors, because that variable already contains quotes.
Does only output the first line of the variable.
3 Solutions collect form web for “Splitting a multi-line environment variable into lines”
The FOR /F command takes the LF’s inserted in the variable as lines separators (this is the natural behavior of FOR /F command), so nothing additional is required in order to process such variable with FOR /F:
@echo off setlocal EnableDelayedExpansion rem Create a variable containing line breaks. set LF=^ %empty line 1/2% %empty line 2/2% set "str=The quick brown!LF!fox jumps over!LF!the lazy dog." set line=0 for /F "delims=" %%a in ("!str!") do ( set /A line+=1 echo Line !line!: %%a )
The key here is expanding the variable with !exclamationMarks!; otherwise the LF will cut the %value%. Also, if you want complete lines separated by LF, use “delims=”. Output example:
Line 1: The quick brown Line 2: fox jumps over Line 3: the lazy dog.
Well as reflex I propose you the following solution:
If python is installed (if not … up to you to install it .. it is usefull 😉 )
in your batch line :
Python MyScriptToExecuteEachLinesFromVar.py varname “myprog.exe -baz 0 -meow”
With the script content:
import sys,os # libraries used : system and operating system if len(sys.argv)>0: # if arguments provided (at least the variable name) varname = sys.argv # the variable name is the second argument (0=script) prefix = " ".join(sys.argv[2:]) # the list of all others are the prefix. lines = os.environ[varname].split('\n') # get the var and split lines for f in lines : print "execute:", prefix, f os.system(prefix+" "+f) # execute each line with the given prefix.
Hope it helps.
echo the variable out to a temporary txt file, then process that txt file line-by-line using a
for /f loop. You should also use delayed expansion to prevent the line breaks from being evaluated inappropriately.
@echo off setlocal enableDelayedExpansion :: // Test environment. Create a variable containing line breaks. set BR=^ :: // note: The two empty lines above are required. set "str=The quick brown!BR!fox jumps over!BR!the lazy dog." :: // Test environment ready. :: // Output to temporary txt file. >"%temp%\tmp.txt" echo(!str! :: // Process the txt file line by line. set "line=0" for /f "usebackq delims=" %%I in ("%temp%\tmp.txt") do ( set /a line += 1 echo Line !line!: %%I rem // myprog.exe -baz 0 -meow %%I ) :: // Delete temporary txt file. del "%temp%\tmp.txt"
That should output
Line 1: The quick brown
Line 2: fox jumps over
Line 3: the lazy dog.
Or if you’d rather avoid temporary files, you could invoke another runtime to supply the environment variable to a
for /f loop. Here’s a JScript hybrid example.
@if (@CodeSection == @Batch) @then @echo off setlocal enableDelayedExpansion :: // Test environment. Create a variable containing line breaks. set BR=^ :: // note: The two empty lines above are required. set "str=The quick brown!BR!fox jumps over!BR!the lazy dog." :: // Test environment ready. :: // Invoke JScript to read the environment variable and return it line-by-line set "line=0" for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0"') do ( set /a line += 1 echo Line !line!: %%I ) :: // end main runtime goto :EOF @end // JScript portion simply echoes %str% from the context of the current process WSH.Echo(WSH.CreateObject('WScript.Shell').Environment('PROCESS')('str'));
Output is the same as above.