如何在 windows 命令提示符下对变量进行字符串替换?

How to do a string replacement on a variable at the windows command prompt?

有没有办法在命令提示符下而不是在批处理文件中进行字符串替换?

一点背景知识:前一段时间我需要注册一个自定义 URI 协议,该协议将通过注册表黑客将调用的 url 转发到 Chrome,这导致:

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

我现在注意到的问题是,通过一些新的 windows 更新,以前被调用的

cnx:// www.someurl.com

在 IE 中现在变成了

cnx://%20www.someurl.com

命令执行时。

因此,我想知道是否有办法在某处进行字符串替换,并从我的 %%a 变量或其他内容中完全删除 cnx://%20

但是我所有使用 https://ss64.com/nt/syntax-replace.html 的尝试都没有奏效。很高兴听到或读到这根本不可能,这样我就可以停止转动我的轮子了。

解决方案在 Window 注册表文件中使用:

@="cmd.exe /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\")"

这会在 Windows 注册表中产生以下命令行:

cmd.exe /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")

重要的是 Windows 命令处理器选项 /V:ON,它为环境变量启用 delayed expansion,如命令提示符 运行 上的帮助输出所述 window cmd /?。选项 /V:ON 必须分别指定到选项 /C(执行命令行后关闭)/K(执行命令行后保持命令进程 运行),因为 /C 之后的所有内容=16=] 或 /K 被解释为要执行的命令行的一部分。

使用/K代替/C可以看到执行此命令行时发生的情况,并且set url可以在命令行执行后由用户执行完了看看环境变量url.

的最终值是多少

命令 window set /? 中 运行 的帮助输出解释了何时以及如何使用延迟环境变量扩展。如果在命令行上定义或修改了环境变量并在与 single line with multiple commands 相同的命令行上引用,则必须使用它。如果在以 ( 开始并以匹配 ) 结束的命令块中定义或修改环境变量,这也是必要的,因为 cmd.exe 解析整个命令块并替换所有 %variable% 在执行此命令块的任何命令之前或在同一命令行上的命令块开始之前按引用环境变量的当前值引用。

另见 How does the Windows Command Interpreter (CMD.EXE) parse scripts?

需要使用!variable!引用环境变量以在启用延迟扩展后延迟扩展此引用。

注意:即使在双引号参数字符串中启用,命令行中的每个感叹号都被解释为 begin/end 延迟扩展环境变量引用。

具有(几乎)相同代码的注释批处理文件将是:

@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