我正在尝试在FOR循环中运行此base64解码-
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=1,2 delims= " %%a IN (file.txt) DO (
FOR /F "tokens=* USEBACKQ" %%g IN (`echo %%a | python -m base64 -d`) do (SET "decode1=%%g")
<nul set /p =!decode1! >> new2.txt
echo. >> new2.txt
)
管道“ |”出现错误在这个时候是出乎意料的。
如果我运行其他示例,则效果很好-
FOR /F "tokens=1,2 delims= " %%a IN (file.txt) DO (
echo %%a | python -m base64 -d > temp.txt
set /p var1=<temp.txt
<nul set /p =!var1! >> new.txt
echo. >> new.txt
)
我只是想立即将python输出输出到变量中,而不是像第二个示例那样随意摆弄。能做到吗?
这是我的file.txt的结构。很简单。它有多行(几百行),其中有2列base64,需要解码为new.txt文件,每列之间都有一个空格,就像在file.txt中一样。
file.txt
Q2FTZlpsZXhlR2dWNWV2Mkxsd0JQdw== Ylk5VEh3M1dRSFhqUHV2WjlMcURyZw==
ZDRhMHhHbndLTDBKa3A4S0piSlB2dw== NWxVODVSNEJUUVZpMGx0UHNERVJvQQ==
RHBHTEFfS0poWWlXbnI3c3NFUzlHQQ== RUcwb3dUWmNYM2UtMzBKVFhOWk1uQQ==
Z3RvanZRMUloMzhsYjkyVXNpNTZ1Zw== LW5rLXdndmYyYzRDLW9oNWg1Nk1Udw==
答案 0 :(得分:1)
您的代码中的主要问题是,this related answer和this related comment中也都显示了转义:
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
。
此外,我建议使用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
上面的脚本包含我要输入的代码的两个特定部分:
明确拒绝通配符,这些通配符会在以后导致for
循环出现问题:
for /F "delims=*?<> eol=*" %%C in ("%%L") do if not "%%C"=="%%L" (
>&2 echo "%%L" contains forbidden characters!
) else (
…
)
%%L
包含当前行字符串。 delims
循环的for /F
选项列出了所有通配符(*
和?
是众所周知的,而<
和>
是未记录的通配符) )。因此,如果当前行包含一个这样的字符,for /F
将以某种方式标记它,因此其元变量%%C
不等于%%L
中的原始行字符串,则整行被跳过并返回错误消息。
排除此类行的原因是循环for %%I in (%%L) do
,该循环用于遍历一行中用空格分隔的项目。标准的for
循环(无/F
开关)旨在循环遍历文件,但实际上,它仅在遇到至少通配符时才访问文件系统,这是我要防止的。 / p>
对照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
处理文本,尽管由于循环正文中仅存在rem/
,所以没有任何反应。无论如何,我只想知道for /F
是否迭代,因为那样我就知道所处理的项是否为有效的Base64编码数据。
这里的线索是for /F
(与任何其他for
循环相反)在至少重复一次时重置退出代码,而在不重复一次时设置退出代码。仅当退出代码为零时,条件运算符&&
才执行以下代码,因此,当迭代for /F
循环时,这意味着遇到了一个禁止的字符,在这种情况下,当前项目被跳过,并出错消息返回。当退出代码不为零时,条件运算符||
执行以下块,因此该项目包含有效的Base64编码数据。
答案 1 :(得分:0)
python -c "import base64, sys; f=open('file.txt', 'rb'); [print(base64.b64decode(lines.split()[0]).decode(), base64.b64decode(lines.split()[1]).decode()) for lines in f]; f.close()" > new2.txt
这避免了使用for
循环... set /p
等来摆弄 ,并让Python读取file.txt
并将输出重定向到{{1 }}。如果输出文件编码是一个问题,那么Python也许也可以写。
如果有关系,请在Python 3.8上进行测试。