Оболочка: внутрифайловое преобразование первого поля текстового файла из десятичного в шестнадцатеричный

Это мой пример текстового файла:

$ 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
Пока это не снова правила, я использую, чтобы выделить больше времени для: а) Больше тестов на ответы. б) Больше возможных ответов. c) Больше предложений/исправлений/деталей. Я предпочитаю принимать ответы на несколько недель позже, чем слишком рано, когда мне нужно будет исправить свой выбор.   -  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 всегда true и никаких дополнительных действий не выполняется , 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 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-"
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