Shell:将文本文件的第一个字段从十进制转换为十六进制

3
这是我的示例文本文件:
$ cat RealVNC\ MRU.reg
"10"="Lamborghini-:1"
"16"="Terminus-"
"20"="Midnighter-:5915"
"35"="ThreepWood-:1"
"81"="Midnighter-:1"
"58"="Midnighter-"

我希望能将第一个字段(在""之间的数字)的值从十进制转换为十六进制(这是Windows的.reg文件,所以我误认为数字是十进制,现在文件太长了,无法手动编辑)。

需要获得的示例结果:

$ cat Hex\ RealVNC\ MRU.reg
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"

可以看到,只有数字发生了改变。 最终的数字必须是两个字符长(RegEdit将其视为不同)。 行的顺序变化并不影响结果,但我认为使用不改变顺序的更“清晰”的解决方案会更好。 我不希望任何数字(无论十进制还是十六进制)超过2个字符,但考虑到这种可能性的解决方案将是最佳的(因为它是一种更通用的解决方案)。 我目前已经测试了:
$ cat RealVNC\ MRU.reg | awk -F \" '{print $2}'
10
16
20
35
81
58

但我不知道如何将十进制转换为十六进制。

我通常使用Bash作为我的shell,但其他基于shell的解决方案(如Perl或Python)也可以接受。


你解决了吗?如果是,请将最有用的答案标记为已接受。 - Juan Diego Godoy Robles
只要不违反规则,我会允许更多时间去:a)对答案进行更多的测试。b)提供更多可能的答案。c)提供更多建议/更正/细节。我更愿意晚几周接受答案,而不是过早地做出选择,这样我就需要纠正它。 - Sopalajo de Arrierez
2个回答

3
一个简单的 awk:
awk -F\" '$2=sprintf("%02X", $2)' OFS=\" file
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"

说明

  • -F\" :将字段分隔符(FS)设置为 "

  • $2=sprintf("%02X", $2) :将$2赋值给其打印版本(sprintf),使用十六进制中大于9的字母'A'到'F'来表示十六进制数字,并在两个数字之间用0填充。

  • OFS=\" :将Output FS设置为与FS相匹配。

$2的赋值总是真的,没有额外的操作,awk总是以其默认操作显示结果。


1
不错的简单解决方案,+1 我之前不知道 OFS - Andreas Louv
1
澄清一下,OP正在主awk脚本之外设置变量OFS:它可以写成:awk 'BEGIN{FS="\"";OFS="\""};$2=sprintf("%02X", $2)' - Andreas Louv

1

当使用带有e标志的替换运算符时,您可以使用Perl来传递一个函数来处理替换值:

echo abc | perl -ne 's/(.+)/uc($1);print/e' # ABC   

你可以使用sprintf函数,通过%X转换来将十进制转换为十六进制:

%x 无符号整数,用十六进制表示
%X 类似于%x,但使用大写字母

$ cat RealVNC\ MRU.reg | perl -ne 's/^"(.*?)"/sprintf("\"%X\"", $1)/e;print;'
"A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"

如果您想在0-F单个值前加上前导零,可以使用前缀格式%02X:
%02X
 ^^L Conversion
 |L Result length
 L- Prefix char

而结果是:

$ cat RealVNC\ MRU.reg | perl -ne 's/^"(.*?)"/sprintf("\"%02X\"", $1)/e;print;'
"0A"="Lamborghini-:1"
"10"="Terminus-"
"14"="Midnighter-:5915"
"23"="ThreepWood-:1"
"51"="Midnighter-:1"
"3A"="Midnighter-"

看起来运行正常,但是我在问题上打了一个错字(已经更正):A必须为0A(所有数字必须是2个字符长)。无论如何,您的方法似乎只有在{10..15}时失败,我可以手动编辑这6个数字。谢谢。 - Sopalajo de Arrierez
@SopalajodeArrierez 是的,当我阅读时,我也实际上认为是这样。简单地使用printf前缀样式%02X(见编辑)。 - Andreas Louv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接