Shell: Преобразуване във файл на първото поле на текстов файл от десетичен в шестнадесетичен

Това е моят примерен текстов файл:

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

И бих искал да преобразувам стойностите на първото поле (числата между "") от десетичен в шестнадесетичен (това е .reg файл за Windows, така че го измислих, мислейки, че числата са в десетична основа и сега файлът е твърде дълъг за ръчно редактиране).

Примерен резултат, който трябва да получа:

$ 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

Но не знам кой да направи промените от dec към hex.

Моята обвивка обикновено е Bash, но се приемат и други решения, извлечени от обвивка (като Perl или Python).


person Sopalajo de Arrierez    schedule 25.10.2015    source източник
comment
Решихте ли го? ако да, моля, отбележете най-полезния отговор като приет.   -  person Juan Diego Godoy Robles    schedule 27.10.2015
comment
Докато това не е отново правило, използвам, за да отделя повече време за: а) Повече тестове на отговорите. б) Още възможни отговори. в) Още предложения/корекции/подробности. Предпочитам да приемам отговорите няколко седмици по-късно, отколкото твърде рано, че ще трябва да коригирам избора си.   -  person Sopalajo de Arrierez    schedule 29.10.2015


Отговори (2)


Просто 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 в шестнадесетична система, като се използват буквите „A“ до „F“ за шестнадесетични цифри, по-големи от 9, и ширина от две цифри с 0 подложка

  • OFS=\" : настройва Oизхода FS да съответства на FS

Присвояването $2 винаги е вярно и не се дава допълнително действие, awk винаги показва резултатите като действие по подразбиране.

person Juan Diego Godoy Robles    schedule 25.10.2015
comment
Хубаво и просто решение, +1 Не знаех за OFS - person andlrc; 26.10.2015
comment
За да изясним, OP задава променливата OFS извън главния awk скрипт: Може да се запише като: awk 'BEGIN{FS="\"";OFS="\""};$2=sprintf("%02X", $2)'. - person andlrc; 26.10.2015

Можете да използвате perl - когато използвате оператора за заместване с флага e, можете да подадете функция за обработка на заместващата стойност:

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

След това можете да използвате sprintf функцията, за да преобразувате десетичния в шестнадесетичен с преобразуването %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-"
person andlrc    schedule 25.10.2015
comment
Изглежда, че работи, но направих правописна грешка във въпроса (коригиран сега): A трябва да бъде 0A (всички числа трябва да са с дължина 2 знака). Както и да е, вашият метод изглежда се проваля само с {10..15} и мога да редактирам тези 6 числа на ръка. Благодари ти. - person Sopalajo de Arrierez; 26.10.2015
comment
@SopalajodeArrierez Да, всъщност смятах, че когато чета също.. просто използвайте стила на префикса printf %02X (вижте редакцията) - person andlrc; 26.10.2015