我有一个相当长的十六进制字符串
Buffer.toString("hex")
,我想将其打印到日志文件中,每个字符串包含 32 个连音。
所以基本上是从
e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000
到
e0 11 02 02 08 09 02 03 00 80 02 02 02 08 09 02 02 08 09 5f 52 0c 80 66 05 44 45 47 2b 44 73 96
21 e0 d0 03 04 04 01 d2 10 44 45 49 46 58 35 32 46 34 47 44 4a 4d 01 00 00 d3 10 44 45 47 2b 44
53 33 37 4f 53 47 4b 32 01 00 00 d4 10 44 45 47 2b 44 53 33 37 47 4b 56 30 33 01 00 00 d5 03 04
04 01 d6 10 44 45 47 2b 44 43 42 32 43 54 47 30 31 01 00 00 d7 10 44 45 47 2b 44 50 44 50 53 5f
5f 5f 5f 01 06 00 90 00
我已经尝试过
hex.replace(/.{64}/g, "$1\n")
将十六进制字符串包裹在32个连音之后,但现在不知道如何在连音之间添加空格。
如果可能的话,我更愿意在一个正则表达式中做到这一点?
您实际上无法在 JavaScript 中的一个正则表达式中执行此操作,因为它不支持可变长度后向查找(一般情况下)、条件替换或
\G
元序列等功能。您可以将字符串拆分为最多 64 个字符的块,然后将这些字符串拆分为最多 2 个字符的块,并用空格和换行符连接拆分:
const hex = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000'
const out = hex
.match(/(.{1,64})/g)
.map(s => s.match(/.{1,2}/g).join(' '))
.join('\n')
console.log(out)
注意,我在第二个正则表达式中使用了
{1,2}
,以防您的数据可能包含奇数个字符。如果不会,您可以简单地使用 .{2}
(或简化为 ..
)。
您还可以定义一个替换函数,使用一个正则表达式将字符串拆分为可变的行长度:
const replacer = n => {
let cnt = 0
return (m) => m + ((++cnt % n) ? ' ' : '\n')
}
const hex = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000'
let out = hex.replace(/../g, replacer(32))
console.log(out)
out = hex.replace(/../g, replacer(16))
console.log(out)
out = hex.replace(/../g, replacer(8))
console.log(out)
要将十六进制字符串格式化为 32 个连音块,每个连音块在 JavaScript 中带有空格和换行符,您可以使用两步方法:
let hexString = "e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000";
hexString = hexString.replace(/(..)/g, "$1 ").trim();
hexString = hexString.replace(/(.{96})/g, "$1\n").trim();
console.log(hexString);
这将为您提供所需的格式化字符串。
您还可以在正则表达式引擎内进行循环:
const src = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000';
function format(src) {
let bytes = 0;
return src.replace(/../g, byte => {
if (bytes === 31) {
bytes = 0;
return `${byte}\n`;
}
bytes++;
return `${byte} `;
});
}
console.log(format(src));
(这可能会被代码打高尔夫球一点,但我想说清楚。)
它使用了字符串
.replace()
方法的特性,该方法允许将函数作为第二个参数传递。 format()
函数保留一个计数器并在换行时重置它。
正则表达式匹配将一遍又一遍地完成,但该正则表达式只会在每次迭代中“吃掉”两个字符,然后每次调用回调。它不会重新扫描整个源字符串。返回字符串是根据回调返回的值在正则表达式引擎内部构建的。
您可以使用
\B
在连音之后断言非单词边界,以便仅在连音之间插入空格:
const hex = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000';
console.log(hex.replace(/.{64}/g, '$&\n').replace(/..\B/g, '$& '))