问题描述
在Linux中我们可以做到
echo -n -e '\x66\x6f\x6f' > test.txt
将十六进制值写入文件.
如何简单地在Windows批处理中完成此操作?
我假设您希望能够写入\ x00到\ xFF范围内的所有可能的二进制字节.不幸的是,纯批处理没有提供执行此操作的简单机制.
但是有很多选择不是很困难.
未公开的!=ExitCodeASCII!
动态变量
!=ExitCodeASCII!
动态变量报告最近运行的外部命令的返回码的ASCII值.但仅限于从\ x20到\ x7E的ASCII码.
我使用延迟扩展,这样我就不必担心有毒字符了.
返回特定错误代码的最简单机制是使用cmd /c exit N
,其中N必须是十进制值.如果要传递十六进制值,则必须先将该值转换为十进制.
Windows批处理使用0xNN表示法指定十六进制值.正如其他人指出的那样,您可以使用set /a val=0x66
进行转换.另一种选择是使用for /l %%N in (0x66 1 0x66) do ...
,优点是您不需要定义中间环境变量来保存值.
@echo off
setlocal enableDelayedExpansion
set "str="
for %%H in (0x66 0x6f 0x6f) do (
for /l %%N in (%%H 1 %%H) do cmd /c exit %%N
set "str=!str!!=ExitCodeASCII!"
)
>test.txt echo(!str!
优势:
- 纯批次
缺点:
- 必须一次构建一个字符一个字符串
- 范围限制为0x20-0x7E
文件
FORFILES命令支持0xNN语法,因此它可以生成大多数字符.但是字符串必须通过CMD/C传递,因此不能用于生成\ 0x00,\ 0x0A或\ 0x0D. (我尚未测试,但我相信所有其他值都可以使用,只要适当地引用或转义有毒字符即可)
@echo off
forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x660x6f0x6f"
优势:
- 纯批次
- 可以一次处理整个字符串
缺点:
- 不支持本地XP
- 不支持0x00、0x0A或0x0D
- 转义/引用有毒字符可能很棘手
证书
CERTUTIL支持-decodeHex动词,该动词可以读取十六进制值并直接写入文件
@echo off
>temp.txt echo(66 6f 6f 0d 0a
certutil -f -decodehex temp.txt test.txt >nul
del temp.txt
优势:
- 纯批次
- 支持所有可能的字节码
- 绝对控制换行符和回车符
- 可以一次处理整个字符串(或文件!)
- 快速
缺点:
- 需要一个临时文件
混合JScript/批处理-简单的解决方案
在批处理脚本中嵌入和执行JScript非常容易.而且JScript具有解释许多转义序列(包括\ xNN)的本机能力.但是,\ xNN转义序列实际上映射到Unicode代码点,因此某些高阶字节代码未映射到正确的字符值.高位字节的结果可能会因计算机的默认字符集而异.
下面,我定义一个:jWrite子例程,该例程可以编写带有嵌入式转义序列的行.如果要编写不包含换行符的字符串,只需在JScript代码中将WriteLine
更改为Write
.
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f" >test.txt
exit /b
:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(eval('"'+WScript.Arguments.Unnamed(0)+'"'));
优势:
- 从XP开始在所有Windows计算机上本机运行的纯脚本
- 非常简单的JScript代码
- 可以一次处理整个字符串
- 许多其他可用的转义序列,例如
\\
,\t
,\r
,\n
等. - 易于将普通文本与转义序列混合使用,但双引号必须为
\x22
缺点:
- 并非所有高阶字节都能给出正确的结果
- 结果取决于您计算机的默认字符集.如果Windows 1252最好
混合JScript/批处理-更健壮但复杂的解决方案
只要您的计算机默认为Windows-1252,编写一些JScript代码以正确解释所有\ xNN代码以提供正确的字节并不太难.而且,如果您的命令会话的活动代码页也与Windows 1252相匹配,那么您可以自由地混入普通文本.
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f"
call :jWrite "Hello\nworld\x80"
exit /b
:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(WScript.Arguments.Unnamed(0).replace(
/\\(\\|b|f|n|r|t|v|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/g,
function($0,$1) {
switch ($1.toLowerCase()) {
case 'x80': return '\u20AC';
case 'x82': return '\u201A';
case 'x83': return '\u0192';
case 'x84': return '\u201E';
case 'x85': return '\u2026';
case 'x86': return '\u2020';
case 'x87': return '\u2021';
case 'x88': return '\u02C6';
case 'x89': return '\u2030';
case 'x8a': return '\u0160';
case 'x8b': return '\u2039';
case 'x8c': return '\u0152';
case 'x8e': return '\u017D';
case 'x91': return '\u2018';
case 'x92': return '\u2019';
case 'x93': return '\u201C';
case 'x94': return '\u201D';
case 'x95': return '\u2022';
case 'x96': return '\u2013';
case 'x97': return '\u2014';
case 'x98': return '\u02DC';
case 'x99': return '\u2122';
case 'x9a': return '\u0161';
case 'x9b': return '\u203A';
case 'x9c': return '\u0153';
case 'x9d': return '\u009D';
case 'x9e': return '\u017E';
case 'x9f': return '\u0178';
default: return eval('"'+$0+'"');
}
}
));
优势:
- 从XP开始在所有Windows计算机上本机运行的纯脚本
- 可以一次处理整个字符串
- 支持从\ x00到\ xFF的所有字节码
- 许多其他可用的转义序列,例如
\\
,\t
,\r
,\n
等. - 易于将普通文本与转义序列混合使用,但双引号必须为
\x22
缺点:
- 如果您的计算机默认为Windows-1252,则仅给出所有字节的正确结果
- 中度复杂的JScript代码
JREPL.BAT-混合JScript/批处理正则表达式文本处理实用程序
我的 JREPL.BAT实用程序是最初设计的在文本文件上执行正则表达式搜索和替换操作.但是它具有使它可以轻松地编写带有嵌入式转义序列的字符串的选项,并且无论计算机使用哪种默认字符集,它都可以为所有字节码提供正确的结果.
如果您的计算机默认使用任何单字节字符集,则可以安全地使用以下内容以及从\ x00到\ xFF的所有可能的转义序列,并且可以自由地将普通文本与转义序列混合在一起.
call jrepl $ "\x66\x6f\x6f" /s "=" /x /o test.txt
/s "="
选项将未定义的环境变量指定为输入源,它被解释为空字符串.第一个$
参数匹配空字符串的结尾.第二个"\x66\x6f\x6f"
参数指定替换值. /x
选项启用替换字符串中的转义序列,而/o test.txt
选项指定输出文件.
如果要追加到test.txt,请添加/APP
选项.
如果您想要\ n行尾而不是\ r \ n(Unix风格而不是Windows),则添加/U
选项
如果您不需要任何新的行终止符,请添加/M
选项.
最后,如果您的计算机未默认使用单字节字符集,则仍可以通过为输出格式指定一个单字节字符集(例如Windows-1252)来为所有转义序列强制使用正确的结果.但是,如果指定的字符集与命令会话的活动代码页不匹配,则只能保证使用转义序列-某些普通的文本字符可能会给出错误的结果.
call jrepl $ "\x66\x6f\x6f" /s "=" /x /o "test.txt|Windows-1252"
优势:
- 从XP开始可在任何Windows计算机上运行的纯脚本
- 可以一次处理整个字符串
- 支持从\ x00到\ xFF的所有字节码
- 许多其他可用的转义序列,例如
\\
,\t
,\r
,\n
等. - 易于将普通文本与转义序列混合使用,但双引号必须为
\x22
或\q
- 不可知的默认字符集-始终可以给出正确的结果
- 一旦您在工具库中有了JREPL,就会发现它有许多用途.这是一个功能强大的工具.
缺点:
- 需要下载第三方脚本
In Linux we can do
echo -n -e '\x66\x6f\x6f' > test.txt
to write HEX values to a file.
How can this be done simply in Windows batch?
I am assuming you want the ability to write all possible binary bytes in the range \x00 through \xFF. Unfortunately, pure batch does not provide a simple mechanism to do this.
But there are a number of options that are not too difficult.
Undocumented !=ExitCodeASCII!
dynamic variable
The !=ExitCodeASCII!
dynamic variable reports the ASCII value of the return code of the most recently run external command. But it is limited to ASCII codes from \x20 through \x7E.
I use delayed expansion so that I don't have to worry about poison characters.
The simplest mechanism to return a specific error code is to use cmd /c exit N
, where N must be a decimal value. If you want to pass in a hex value, then the value must first be converted to decimal.
Windows batch uses 0xNN notation to specify a hex value. As others have noted, you can use set /a val=0x66
to do the conversion. Another option is to use for /l %%N in (0x66 1 0x66) do ...
, the advantage being you don't need to define an intermediate environment variable to hold the value.
@echo off
setlocal enableDelayedExpansion
set "str="
for %%H in (0x66 0x6f 0x6f) do (
for /l %%N in (%%H 1 %%H) do cmd /c exit %%N
set "str=!str!!=ExitCodeASCII!"
)
>test.txt echo(!str!
Advantages:
- Pure batch
Disadvantages:
- Must build string one character at a time
- Range limited to 0x20 - 0x7E
FORFILES
The FORFILES command supports 0xNN syntax, so it can generate most characters. But the string must pass through CMD /C, so it cannot be used to generate \0x00, \0x0A, or \0x0D. (I haven't tested, but I believe all other values work, provided poison characters are appropriately quoted or escaped)
@echo off
forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x660x6f0x6f"
Advantages:
- Pure batch
- Can process an entire string in one pass
Disadvantages:
- No native XP support
- No support for 0x00, 0x0A, or 0x0D
- Escaping / quoting of poison characters can be tricky
CERTUTIL
The CERTUTIL supports a -decodeHex verb that can read hex values and write directly to a file
@echo off
>temp.txt echo(66 6f 6f 0d 0a
certutil -f -decodehex temp.txt test.txt >nul
del temp.txt
Advantages:
- Pure batch
- All possible bytes codes supported
- Absolute control of newlines and carriage returns
- Can process an entire string (or file!) in one pass
- Fast
Disadvantages:
- Requires a temp file
Hybrid JScript / batch - simple solution
It is very easy to embed and execute JScript within a batch script. And JScript has native ability to interpret many escape sequences, including \xNN. However, the \xNN escape sequences actually map to Unicode code points, so some of the high order byte codes do not map to the correct character values. And the results for high order bytes can vary depending on your machines default character set.
Below I define a :jWrite subroutine that can write lines with embedded escape sequences. Simply change the WriteLine
to Write
in the JScript code if you want to write strings without the newline characters.
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f" >test.txt
exit /b
:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(eval('"'+WScript.Arguments.Unnamed(0)+'"'));
Advantages:
- Pure script that runs natively on all Windows machines from XP onward
- Very simple JScript code
- Can process entire strings in one pass
- Many other escape sequences available, such as
\\
,\t
,\r
,\n
, etc. - Easy to mix ordinary text with escape sequences, but double quote must be
\x22
Disadvantages:
- Not all high order bytes give the correct result
- Results are dependent on your machine's default character set. Best if Windows 1252
Hybrid JScript / batch - more robust, but complex solution
It is not too difficult to write some JScript code to properly interpret all \xNN codes to give the correct byte as long as your machine defaults to Windows-1252. And if your command session's active code page also matches Windows 1252, then you can freely mix in normal text.
@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f"
call :jWrite "Hello\nworld\x80"
exit /b
:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(WScript.Arguments.Unnamed(0).replace(
/\\(\\|b|f|n|r|t|v|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/g,
function($0,$1) {
switch ($1.toLowerCase()) {
case 'x80': return '\u20AC';
case 'x82': return '\u201A';
case 'x83': return '\u0192';
case 'x84': return '\u201E';
case 'x85': return '\u2026';
case 'x86': return '\u2020';
case 'x87': return '\u2021';
case 'x88': return '\u02C6';
case 'x89': return '\u2030';
case 'x8a': return '\u0160';
case 'x8b': return '\u2039';
case 'x8c': return '\u0152';
case 'x8e': return '\u017D';
case 'x91': return '\u2018';
case 'x92': return '\u2019';
case 'x93': return '\u201C';
case 'x94': return '\u201D';
case 'x95': return '\u2022';
case 'x96': return '\u2013';
case 'x97': return '\u2014';
case 'x98': return '\u02DC';
case 'x99': return '\u2122';
case 'x9a': return '\u0161';
case 'x9b': return '\u203A';
case 'x9c': return '\u0153';
case 'x9d': return '\u009D';
case 'x9e': return '\u017E';
case 'x9f': return '\u0178';
default: return eval('"'+$0+'"');
}
}
));
Advantages:
- Pure script that runs natively on all Windows machines from XP onward
- Can process entire strings in one pass
- All bytes codes from \x00 through \xFF are supported
- Many other escape sequences available, such as
\\
,\t
,\r
,\n
, etc. - Easy to mix ordinary text with escape sequences, but double quote must be
\x22
Disadvantages:
- Only gives correct results for all bytes if your machine defaults to Windows-1252
- Moderately complex JScript code
JREPL.BAT - Hybrid JScript/batch regular expression text processing utility
My JREPL.BAT utility was originally designed to perform regular expression search and replace operations on text files. But it has options that allow it to easily write strings with embedded escape sequences, and it can give the correct result for all byte codes no matter what default character set your machine uses.
If your machine defaults to any single byte character set, then you can safely use the following with all possible escape sequences from \x00 through \xFF, and you can freely mix in normal text along with escape sequences.
call jrepl $ "\x66\x6f\x6f" /s "=" /x /o test.txt
The /s "="
option specifies an undefined environment variable as the input source, which is interpreted as an empty string. The first $
argument matches the end of the empty string. The second "\x66\x6f\x6f"
argument specifies the replacement value. The /x
option enables escape sequences within the replacement string, and the /o test.txt
option specifies the output file.
If you want to append to test.txt, then add the /APP
option.
If you want \n end-of-line instead of \r\n, (Unix style instead of Windows) then add the /U
option
If you don't want any new line terminators, then add the /M
option.
Lastly, if your machine does not default to a single byte character set, you can still force the correct result for all escape sequences by specifying a single byte character set like Windows-1252 for the output format. However, if the specified character set does not match your command session's active code page, then only escape sequences are guaranteed to work - some normal text characters may give the wrong result.
call jrepl $ "\x66\x6f\x6f" /s "=" /x /o "test.txt|Windows-1252"
Advantages:
- Pure script that runs on any Windows machine from XP onward
- Can process entire strings in one pass
- All bytes codes from \x00 through \xFF are supported
- Many other escape sequences available, such as
\\
,\t
,\r
,\n
, etc. - Easy to mix ordinary text with escape sequences, but double quote must be
\x22
or\q
- Default character set agnostic - can always give the correct result
- Once you have JREPL in your arsenal of tools, you will find many uses for it. It is a powerful tool.
Disadvantages:
- Requires download of a 3rd party script
这篇关于将HEX值写入Windows批处理中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!