Shell: In-file converting first field of a text file from decimal to hexadecimal

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

This is my example text file:

$ cat RealVNC\ MRU.reg "10"="Lamborghini-:1" "16"="Terminus-" "20"="Midnighter-:5915" "35"="ThreepWood-:1" "81"="Midnighter-:1" "58"="Midnighter-" 

And I would like to convert values of the first field (the numbers between "") from decimal to hexadecimal (it is a .reg file for Windows, so I meesed it up thinking the numbers were in a decimal base, and now the file is too long to manually edit).

Example result that I need to obtain:

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

As can be seen, only the numbers have changed. Resulting numbers must be two characters long (RegEdit considers them different).
Changes in the order of the lines don't bother here, but I think it would be more "clean" a solution that doesn't change it.

I don't expect any number (be it decimal or hex) will have more than 2 characters, but a solution that considers this possibility will be best (as it is a more generic solution).

I have tested so far:

$ cat RealVNC\ MRU.reg | awk -F \" '{print $2}' 10 16 20 35 81 58 

But I don't know who to in-line make the changes from dec to hex.

My shell is usually Bash, but other shell-derivated solutions (like Perl or Python) are accepted too.

回答1:

A simple 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-" 

Explanation

  • -F\" : sets field separator (FS) to "

  • $2=sprintf("%02X", $2) : $2 is assigned to it’s printed version ( sprintf) with a %02X mask in hexadecimal using the letters 'A' to 'F' for hex digits greater than 9 and a two digits width with 0 padding

  • OFS=\" : sets the Output FS to match FS

The $2 assignation is always true and no additional action is given , awk always displays the results as it's default action.



回答2:

You can use perl - when using the substitution operator with the e flag you can pass a function to handle the replace value:

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

You can then use sprintf function to convert decimal to hex with the %X conversion:

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

If you want leading zero on 0-F single values you can use the prefix format %02X:

%02X  ^^L Conversion  |L Result length  L- Prefix char 

And the result:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!