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

时间:2015-10-25 23:03:32

标签: bash base inline-editing

这是我的示例文本文件:

$ 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

但是我不知道谁在线改变从十进制到十六进制。

我的shell通常是Bash,但也接受其他shell派生的解决方案(如Perl或Python)。

2 个答案:

答案 0 :(得分: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),使用十六进制的%02X掩码 字母&#39; A&#39;到&#39; F&#39;对于大于9的十六进制数字和两位数 宽度0填充

  • OFS=\":设置 O 输出 FS 以匹配 FS

$2分配始终是 true ,并且不会给出其他操作,awk始终会将结果显示为默认操作。

答案 1 :(得分:1)

你可以使用perl - 当substitution operator使用e标志时,你可以传递一个函数来处理替换值:

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

然后,您可以使用sprintf function通过%X转换将十进制转换为十六进制:

  

%x an unsigned integer, in hexadecimal
  %X like %x, but using upper-case letters

$ 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-"