Разбор и передача специальных символов в пакетных файлах Windows - PullRequest
4 голосов
/ 11 марта 2019

Я пытаюсь написать командный файл, который может принимать пользовательский ввод FTP-ссылки, анализировать пользователя, пароль и домен, записывать их в файл и вызывать файл как ввод для команды FTP. Я успешно написал его, пока у кого-то не было пароля с !.

FTP-ссылки создаются системой и могут содержать специальные символы (например: !, ^, *).

Я использую setlocal delayedexpansion, поскольку я читаю полную строку (то есть: ftp://userid:password@some.domain.com) в цикле for, используя /, : и @ в качестве разделителей.

Я попытался проявить творческий подход и выполнить 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-ссылки:

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

К сожалению, специальный символ может находиться в любом месте строки пароля или, возможно, в имени пользователя. Кроме того, имя пользователя и пароль не имеют одинаковой длины (то есть: 8 символов каждый). Я нашел это трудным путем.

Любая помощь очень ценится.

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

Это тривиально (если вы знаете, что делать).
Ключ заключается в расширении параметра 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´ or OFF`.

1 голос
/ 12 марта 2019

Вы, конечно, можете просто не устанавливать эти переменные вообще:

@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
...