我想使用批处理将用户输入的包含与号的字符串放入剪贴板。我可以修改字符串,然后使用 setlocal EnableExtensions EnableDelayedExpansion
将其打印到终端
但我无法将其通过管道传输到剪贴板。
这里有一个深入的讨论,讨论了为什么管道会破坏东西,但我无法很好地理解它来解决我的问题。 https://www.robvanderwoude.com/battech_inputvalidation_setp.php
setlocal EnableExtensions EnableDelayedExpansion
set /P "INPUT=Paste the stuff in the terminal please"
set "SEARCHTEXT=+"
set REPLACETEXT=%%2B
for /F "delims=" %%A in ("%INPUT%") do (
set "string=%%A"
set "modified=!string:%SEARCHTEXT%=%REPLACETEXT%!"
echo !modified! | clip
)
因为我试图修改的字符串中包含“&username”,所以我得到的输出是: “用户名”未被识别为内部或外部命令, 可运行的程序或批处理文件。
如果我只echo !modified!
,就没有错误。如何将任意未清理的字符串放入剪贴板?
最佳答案
您代码中的主要问题是以下行:
echo !modified! | clip
A pipe (|
)为任何一方创建一个新的 cmd
实例。你有 delayed expansion在您的脚本中启用,因此变量 !modified!
在解析整个命令行时会扩展,然后执行管道,然后是左侧的新 cmd
实例side 接收已经扩展的变量,包括所有潜在的有毒字符,例如 &
。
为了防止!modified!
立即展开,我们需要escape ^^!
之类的感叹号(^^
首先转义为单个 ^
,因此 ^!
是在延迟扩展阶段留下),这让 !
被视为文字字符,并且一开始不会发生变量扩展。
新的 cmd
实例(在我们的情况下为管道的左侧)现在已禁用延迟扩展,因此我们需要显式实例化另一个(嵌套的)实例并启用延迟扩展(通过cmd /V
):
cmd /V /C echo(^^!modified^^!| clip
通过这种技术,我们强制变量 !modified!
尽可能晚地扩展,因此通过最内层的 cmd
实例,这避免了扩展字符串到被任何其他实例接收,因此,有毒字符对解析器隐藏。
另外,我用了保险箱echo
变体 echo(...
,因为 echo ...
在某些情况下可能会失败(假设 ...
是文字字符串 /?
). 此外,我删除了 |
前面的 SPACE,因为这样也会无意中回显。
关于batch-file - 如何使用批处理脚本将未清理的字符串复制到剪贴板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57191176/