Основная проблема в вашем коде - это отсутствие экранирования, как показано в этот связанный ответ , а также этот связанный комментарий :
FOR /F "tokens=* USEBACKQ" %%g IN (`echo %%a | python -m base64 -d`) do (SET "decode1=%%g")
следует читать:
FOR /F "tokens=* USEBACKQ" %%g IN (`echo %%a ^| python -m base64 -d`) do (SET "decode1=%%g")
, чтобы скрыть трубу |
из первой фазы синтаксического анализа, которая обрабатывает все for /F
l oop определение.
Кроме того, рекомендую использовать set /p ="!decode1!"
, а не set /p =!decode1!
, чтобы сохранить окружающие кавычки, которые могут присутствовать в значении переменной decode1
.
В любом случае, я хочу предоставить альтернативный метод вашего подхода к преобразованию, на основе инструмента certutil
, который доступен с Windows XP, я думаю:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SEP= " & rem // (separator character or string for the output)
set "_TMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary file for conversion of single items)
set "_CHR=%TEMP%\%~n0_%RANDOM%.chr" & rem // (temporary file to hold just a given separator)
rem // Create a temporary file that only contains a single separator as specified:
> nul forfiles /P "%~dp0." /M "%~nx0" /C "cmd /V /C ^> 0x22!_CHR!0x22 echo(!_SEP!0x1A"
> nul copy "%_CHR%" /A + nul "%_CHR%" /B
rem // Loop through all non-empty lines read from the console input:
for /F "tokens=* eol= " %%L in ('more') do (
rem // Explicitly deny wildcard characters that would cause problems with a `for` loop later:
for /F "delims=*?<> eol=*" %%C in ("%%L") do if not "%%C"=="%%L" (
>&2 echo "%%L" contains forbidden characters!
) else (
rem // Loop through whitespace-separated items in the current line:
set "FIRST=#"
for %%I in (%%L) do (
rem // Check current items against list of all valid characters for Base64 encoding:
(
for /F "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= eol==" %%D in ("%%I") do rem/
) && (
>&2 echo "%%I" is not valid Base64 encoding!
) || (
rem // Actually perform the Base64 decoding of the current item:
> "%_TMP%" echo(%%I
> nul certutil -f -v -decode "%_TMP%" "%_TMP%"
rem // Write the resulting data to the console output:
if not defined FIRST type "%_CHR%"
type "%_TMP%"
set "FIRST="
)
)
if not defined FIRST echo/
)
)
rem // Clean up temporary files:
del "%_TMP%" "%_CHR%"
endlocal
exit /B
Этот скрипт, назовем его decode-b64-chunks.bat
, читает в кодировке Base64 данные из консоли и записывает декодированные данные в консоль. Чтобы преобразовать образец входного файла file.txt
из вашего вопроса в новый файл в текущем рабочем каталоге, используйте следующую командную строку:
decode-b64-chunks.bat < "file.txt" > "new.txt"
Результирующий файл с именем new.txt
в конечном итоге будет содержать следующий текст :
CaSfZlexeGgV5ev2LlwBPw bY9THw3WQHXjPuvZ9LqDrg
d4a0xGnwKL0Jkp8KJbJPvw 5lU85R4BTQVi0ltPsDERoA
DpGLA_KJhYiWnr7ssES9GA EG0owTZcX3e-30JTXNZMnA
gtojvQ1Ih38lb92Usi56ug -nk-wgvf2c4C-oh5h56MTw
Приведенный выше скрипт содержит две конкретные части кода, которые я хочу go в:
Явно отрицать символы подстановки, которые могут вызвать проблемы с for
l oop позже:
for /F "delims=*?<> eol=*" %%C in ("%%L") do if not "%%C"=="%%L" (
>&2 echo "%%L" contains forbidden characters!
) else (
…
)
%%L
содержит текущую строку строки. Параметр delims
в for /F
l oop перечисляет все символы подстановки (*
и ?
хорошо известны, а <
и >
недокументированы). Таким образом, если текущая строка содержит один такой символ, for /F
каким-то образом его токенизирует, поэтому его метапеременная %%C
не равна исходной строке строки в %%L
, тогда вся строка пропускается и появляется сообщение об ошибке возвращается.
Причиной исключения таких строк является l oop for %%I in (%%L) do
, который используется для обхода элементов, разделенных пробелами в строке. Стандартный for
l oop (без переключателя /F
) предназначен для l oop через файлы, но на самом деле он обращается к файловой системе только тогда, когда встречается хотя бы подстановочный знак, что я хочу предотвратить. .
Проверить текущие элементы на соответствие списку всех допустимых символов для кодировки Base64:
)
for /F "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= eol==" %%D in ("%%I") do rem/
) && (
>&2 echo "%%I" is not valid Base64 encoding!
) || (
…
)
Параметр delims
перечисляет все символы, разрешенные в кодировке Base64- закодированная строка. Теперь, если элемент %%I
содержит только такие символы, это строка только с разделителями, которая for /F
пропускается; если встречается любой другой символ, for /F
обрабатывает текст, хотя ничего не происходит, так как в теле l oop содержится только rem/
. В любом случае, я просто хочу знать, повторяется ли for /F
или нет, потому что тогда я знаю, является ли обработанный элемент действительными данными в кодировке Base64.
Подсказка здесь в том, что for /F
(в отличие от любого другого for
loops) сбрасывает код выхода, когда он повторяется хотя бы один раз, и устанавливает его, когда это не так. Условный оператор &&
выполняет следующий код только тогда, когда код выхода равен нулю, поэтому при итерации for /F
l oop, что означает обнаружение запрещенного символа, в этом случае текущий элемент пропускается и появляется сообщение об ошибке возвращается. Условный оператор ||
выполняет следующий блок, когда код выхода не равен нулю, поэтому элемент содержит допустимые данные в кодировке Base64.