如何使用批处理脚本将未清理的字符串复制到剪贴板

How to copy un-sanitized string to clipboard with batch script

我想使用批处理将用户输入的包含 & 符号的字符串放入剪贴板。我可以修改字符串,然后使用 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”,所以我得到的输出是: 'username' 未被识别为内部或外部命令, 可运行的程序或批处理文件。

如果我只echo !modified!,就没有错误。如何将任意未清理的字符串放入剪贴板?

您的代码中的主要问题是以下行:

echo !modified! | clip

A pipe (|) creates a new cmd instance for either side. You have got delayed expansion 在您的脚本中启用,因此当解析整个命令行时变量 !modified! 会扩展,然后执行管道,然后是新的 cmd 实例对于左侧接收已经扩展的变量,包括所有潜在的有毒字符,例如 &

为了防止!modified!立即展开,我们需要escape^^!这样的感叹号(^^首先转义为单个^, 所以 ^! 在延迟扩展阶段留下), 这让 ! 被视为文字字符, 并且一开始不会发生变量扩展.

新的 cmd 实例(在我们的情况下为管道的左侧)现在已禁用延迟扩展,因此我们需要显式实例化另一个(嵌套的)实例并启用延迟扩展(通过 cmd /V):

cmd /V /C echo(^^!modified^^!| clip

通过这种技术,我们强制变量 !modified! 尽可能晚地扩展,因此由最内层的 cmd 实例扩展,这避免了扩展的字符串被任何其他实例接收,因此,有害字符对解析器隐藏了。


此外,我使用了安全的 echo 变体 echo(...,因为 echo ... 在某些情况下可能会失败(假设 ... 是文字字符串 /?).此外,我删除了|前面的SPACE,因为这样也会无意中回显。