3

我想使用批处理将包含&符号的用户输入字符串放入剪贴板。我可以修改字符串,并且可以使用它打印到终端,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' 不是内部或外部命令、可运行程序或批处理文件。

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

4

1 回答 1

4

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

echo !modified! | clip

管道 ( |)cmd为任一侧创建一个新实例。您在脚本中启用了延迟扩展!modified!,因此在解析整个命令行时变量会被扩展,然后执行管道,然后cmd左侧的新实例接收已经扩展的变量,包括所有潜在的有毒字符,比如&,例如。

为了防止!modified!立即扩展,我们需要转义感叹号,例如^^!(^^成为首先转义为单个^,因此^!在延迟扩展阶段留下),这使得将!被视为文字字符并且首先不会发生变量扩展。

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

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

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


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

于 2019-07-24T22:08:57.580 回答