'Pretty print' windows %PATH% variable - how to split on ';' in CMD shell
The simple way is to use
for %a in ("%path:;=";"%") do @echo %~a
This works for all without ;
in the path and without "
around a single element
Tested with path=C:\qt\4.6.3\bin;C:\Program Files;C:\documents & Settings
But a "always" solution is a bit complicated
EDIT: Now a working variant
@echo off
setlocal DisableDelayedExpansion
set "var=foo & bar;baz<>gak;"semi;colons;^&embedded";foo again!;throw (in) some (parentheses);"unmatched ;-)";(too"
set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
rem ** This is the key line, the missing quote is intended
set var=%var:""="%
set "var=%var:"=""%"
set "var=%var:;;="";""%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
set "var=%var:"=""%"
set "var=%var:"";""=";"%"
set "var=%var:"""="%"
setlocal EnableDelayedExpansion
for %%a in ("!var!") do (
endlocal
echo %%~a
setlocal EnableDelayedExpansion
)
What did I do there?
I tried to solve the main problem: that the semicolons inside of quotes should be ignored, and only the normal semicolons should be replaced with ";"
I used the batch interpreter itself to solve this for me.
- First I have to make the string safe, escaping all special characters.
- Then all
;
are replaced with^;^;
- and then the trick begins with the line
set var=%var:"=""%"
(The missing quote is the key!).
This expands in a way such that all escaped characters will lose their escape caret:var=foo & bar;;baz<>gak;;"semi^;^;colons^;^;^&embedded";;foo again!;;
...
But only outside of the quotes, so now there is a difference between semicolons outside of quotes;;
and inside^;^;
.
Thats the key.
A simple one liner to prettying printing the PATH
environment variable:
ECHO.%PATH:;= & ECHO.%
If your PATH
was equal to A;B;C
the above string substitution will change this to ECHO.A & ECHO.B & ECHO.C
and execute it all in one go. The full stop prevents the "ECHO is on" messages from appearing.
An update to Stephan Quan's very clever one-liner solution: The problem I encountered was that a trailing semi-colon - (and maybe two successive semi-colons, i.e. empty path element) would cause the message "ECHO is on" to appear. I solved this by inserting a period immediately after the second ECHO statement (which is the syntax to suppress ECHO is on/off messages). However, it will result in an extra empty line:
ECHO %PATH:;= & ECHO.%
I have minor improvements to jeb's clever "always" solution. Currently jeb's solution has the following issues:
- If the leading path is enclosed in quotes, then the first output starts with ""
- If the trailing path is enclosed in quotes, then the last output ends with ""
- If any path contains harmless but non-functional consecutive "", then the output preserves the ""
- If var contains consecutive ;; delimiters then outputs ECHO is off
This solution fixes the minor issues, plus it uses 2 fewer substitutions. Also I eliminated the unnecessary repeated enabling/disabling delayed expansion within the loop. (Edit on 2011-10-30 simplified the ENDLOCAL logic)
@echo off
setlocal DisableDelayedExpansion
set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
set var=%var:""="%
set "var=%var:"=""Q%"
set "var=%var:;;="S"S%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
setlocal EnableDelayedExpansion
set "var=!var:"Q=!"
for %%a in ("!var:"S"S=";"!") do (
if "!!"=="" endlocal
if %%a neq "" echo %%~a
)
If you want to see a blank line for each empty path resulting from consecutive ;; delimiters, then the last line of the FOR loop can simply read echo(%%~a
instead.
Or perhaps it would be more obvious to display empty paths as "" using:if %%a=="" (echo "") else echo %%~a
The various empty path fixes work for jeb's simple solution as well.
UPDATE: Here is a simple one-liner using JREPL.BAT
You can use my JREPL.BAT regular expression text processing utility to achieve a simple, very robust solution. JREPL.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.
jrepl "([^;\q]+|\q.*?(\q|$))+" $0 /x /jmatch /s path