在 Windows 个批处理文件中解析和传递特殊字符

Parsing and passing special characters in Windows batch files

我正在尝试编写一个批处理文件,该文件可以获取 FTP link 的用户输入,解析出用户、密码和域,将它们写入文件并调用该文件作为 FTP 命令的输入。我已经成功编写了它,直到有人在其中输入了带有 ! 的密码。

FTP link 是系统生成的,可能包含特殊字符(即:!^*)。

我使用 setlocal delayedexpansion 在 for 循环中使用 /: 和 [=21] 读取完整字符串(即:ftp://userid:password@some.domain.com) =] 作为分隔符。

我尝试发挥创意并在解析输出后执行 endlocal delayedexpansion,但随后标记不起作用,因为我要结束扩展。我也试过将每个标记写入其自己的文件,然后将文件的内容分配为变量,但没有成功。

我觉得应该有办法做到这一点,但我一直碰壁。

这是我的代码片段:

@ECHO OFF
setlocal enableextensions enabledelayedexpansion
echo Example FTP link:
echo.
echo "ftp://xxxxxxxx:yyyyyyyy@some.where.com"
echo.
set /p ftplink= Please enter full FTP link:  
echo.
set /p ftpfile= Please provide the file name you want to download:  

:FTPbat
:: Generate a bat file for FTP retrieval
for /f "tokens=1-4 delims=/:@" %%a in ("%ftplink%") do (
    set ftpdomain=%%~d
    set ftpuser=%%~b
    set ftppass=%%~c
    )

    echo open %ftpdomain%> get.ftp
    echo %ftpuser%>> get.ftp
    echo %ftppass%>> get.ftp
    echo binary>> get.ftp
    echo hash>> get.ftp
    echo mget %ftpfile%>> get.ftp
    echo disconnect>> get.ftp
    echo quit>> get.ftp 
:GetFTPFile
CLS
FTP -i -s:get.ftp

这是一个例子FTP link:

ftp://username:pas!word@somewhere.com

不幸的是,特殊字符可以出现在密码字符串中的任何位置,也可能出现在用户名中。此外,用户名和密码的长度不统一(即:每个 8 个字符)。我很难找到它。

非常感谢任何帮助。

这很简单(如果你知道该怎么做)。
关键是仅在禁用延迟扩展模式下扩展 FOR 参数(否则延迟扩展阶段将修改 ! 个字符)。
但是要使用可变内容,请始终使用延迟扩展模式(因为只有延迟扩展才能安全地扩展任何内容)。
所以你需要切换模式。

参考:SO:Windows 命令解释器 (CMD.EXE) 如何解析脚本?

SETLOCAL EnableDelayedExpansion    
(
  for /f "tokens=1-4 delims=/:@" %%a in ("!ftplink!") do (
    SETLOCAL DisableDelayedExpansion
    set "ftpdomain=%%~d"
    set "ftpuser=%%~b"
    set "ftppass=%%~c"

    SETLOCAL EnableDelayedExpansion    
    echo open !ftpdomain!
    echo !ftpuser!
    echo !ftppass!
    echo binary
    echo hash
    echo mget !ftpfile!
    echo disconnect
    echo quit
    ENDLOCAL
    ENDLOCAL
  )
) > get.ftp

这段代码很简单,最好使用

...
(echo open !ftpdomain!)
(echo(!ftpuser!)
(echo(!ftppass!)
(echo binary)
...

括起来的括号避免了尾随空格的问题。
echo( 之后丑陋的左括号是为了避免出现空变量或包含问题内容的变量的问题,例如 /?ON´ orOFF`.

您当然可以根本不设置这些变量:

@Echo Off
Echo Example FTP link:
Echo(
Echo "ftp://username:password@domain.ext"
Echo(
Set /P "ftplink= Please enter full FTP link: "
Echo(
Set /P "ftpfile= Please provide the file name you want to download: "

(For /F "Tokens=2-4 delims=/:@" %%A In ("%ftplink%")Do (Echo open %%C
    Echo %%A
    Echo %%B
    Echo binary
    Echo hash
    Echo mget %ftpfile%
    Echo disconnect
    Echo quit))>get.ftp

ClS
FTP -i -s:get.ftp

您仍然可以保存这些变量供以后在脚本中使用,如果需要,您只是不需要在循环中使用它们!

(For /F "Tokens=2-4 delims=/:@" %%A In ("%ftplink%")Do (Set "ftpuser=%%A"
    Set "ftppass=%%B"
    Set "ftpdomain=%%C"
    Echo open %%C
    Echo %%A
    Echo %%B
    Echo binary
    Echo hash
    Echo mget %ftpfile%
    Echo disconnect
    Echo quit))>get.ftp