Is there a way to do string replacement, at the command prompt, as opposed to inside a batch file?
A little background: A while ago I needed to register a custom URI protocol that would forward the invoked url to Chrome via a registry hack which resulted in:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CNX]
@="Chrome HTML Document"
"URL Protocol"=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CNX\DefaultIcon]
@="C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe,0"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CNX\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CNX\shell\open]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CNX\shell\open\command]
@="cmd /c cd \"C:\\Program Files (x86)\\Google\\Chrome\\Application\\\" & FOR /f \"tokens=1-3delims=?#\" %%a IN (\"%1\") DO (if \"%%a#%%b%%c\"==\"%1\" (chrome.exe %1) else (chrome.exe %%a#%%c%%b) )"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\ProtocolExecute\CNX]
"WarnOnOpen"=dword:00000000
The problem that I have noticed now is that via some new windows update, what used to be invoked as
cnx:// www.someurl.com
in IE now gets turned into
cnx://%20www.someurl.com
when the command is executed.
Therefore, I am wondering if there is a way to do a string replace somewhere, and completely strip out cnx://%20 from my %%a variable or something?
But all my attempts at using How-to: Edit/Replace text within a Variable have not worked. It would be great to hear or read that it is not possible at all, so I can stop spinning my wheels.
The solution is using in Window registry file:
@="cmd.exe /D /V:ON /C cd /D \"C:\\Program Files (x86)\\Google\\Chrome\\Application\\\" & set \"url=%1\" & set \"url=!url:cnx://%%20=!\" & set \"url=!url:cnx://=!\" & for /F \"tokens=1-3 delims=?#\" %%a in (\"!url!\") do if \"%%a#%%b%%c\"==\"!url!\" (chrome.exe \"!url!\") else (chrome.exe \"%%a#%%c%%b\")"
This results in the following command line in Windows registry:
cmd.exe /D /V:ON /C cd /D "C:\Program Files (x86)\Google\Chrome\Application\" & set "url=%1" & set "url=!url:cnx://%%20=!" & set "url=!url:cnx://=!" & for /F "tokens=1-3 delims=?#" %%a in ("!url!") do if "%%a#%%b%%c"=="!url!" (chrome.exe "!url!") else (chrome.exe "%%a#%%c%%b")
Important is the Windows Command Processor option /V:ON which enables delayed expansion for environment variables as explained by help output on running in a command prompt window cmd /?. Option /V:ON must be specified left to option /C (close after execution of command line) respectively /K (keep command process running after execution of command line) because everything after /C or /K is interpreted as part of the command line to execute.
The use of /K instead of /C makes it possible to see what happens on the execution of this command line and set url can be executed by the user after the command line execution finished to see what the final value of the environment variable url is.
The cmd option /D is for preventing accessing the registry for the AutoRun registry string value of the Command Processor and executing the command line configured with the AutoRun registry value first before executing the command line specified with the argument string(s) after option /C or /K if AutoRun exists. There is by Windows default no AutoRun registry value either under the registry key HKEY_CURRENT_USER\Software\Microsoft\Command Processor nor under the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor.
The help output on running in a cmd window set /? explains when and how to use delayed environment variable expansion. It must be used if an environment variable is defined or modified on a command line and referenced on same command line as it is here the case with single line with multiple commands. It is also necessary if an environment variable is defined or modified within a command block starting with ( and ending with matching ) because of cmd.exe parses the entire command block and replaces all %variable% references by current value of referenced environment variable before executing any command of this command block or left to begin of command block on same command line.
See also How does the Windows Command Interpreter (CMD.EXE) parse scripts?
It is necessary to reference environment variables with !variable! to expand this reference delayed after having enabled delayed expansion.
Note: Every exclamation mark in command line is interpreted as begin/end of delayed expanded environment variable reference once being enabled even inside a double quoted argument string.
A commented batch file with (nearly) same code would be:
@echo off
rem Explicitly enable command extensions although enabled by default
rem and delayed environment variable expansion disabled by default.
setlocal EnableExtensions EnableDelayedExpansion
rem Change current directory to directory containing Google Chrome browser.
cd /D "%ProgramFiles(x86)%\Google\Chrome\Application\"
rem Define environment variable url with value of first
rem argument with surrounding double quotes removed.
set "url=%~1"
rem Exit batch file if called without any argument or with just "".
if not defined url goto EndBatch
rem Remove case-insensitive all occurrences of string "cnx://"
rem with an additional percent encoded space from the url argument.
set "url=!url:cnx://%%20=!"
rem Remove case-insensitive all occurrences of string "cnx://".
set "url=!url:cnx://=!"
rem Split up the url strings on question mark and hash and assign just
rem first three ?# delimited substrings to loop variables a, b, and c.
rem FOR would not run any command in command block on url starting with
rem a semicolon. Run Google Chrome with the url if first substring with #
rem and the two other substrings appended is case-sensitive equal the url.
rem Otherwise run Google Chrome with redefined url with second and third
rem substring exchanged after first substring and hash character.
for /F "tokens=1-3 delims=?#" %%a in ("!url!") do (
if "%%a#%%b%%c" == "!url!" (
start "" chrome.exe "!url!"
) else (
start "" chrome.exe "%%a#%%c%%b"
)
)
rem Restore initial environment on calling the batch file which means
rem discarding all environment variables defined or modified in block
rem above like environment variable url, restore initial current directory
rem as it was before using command CD and restore also initial states of
rem command extensions (most likely enabled) and delayed expansion (most
rem likely disabled).
:EndBatch
endlocal