Скрипт для преобразования символов ASCII в нотацию Unicode «<Uxxx>»

Я делаю некоторые изменения в файлах локали Linux /usr/share/i18n/locales (например, pt_BR ), и требуется, чтобы строки формата (например, %d-%m-%Y %H:%M ) указывались в Unicode , где каждый (в данном случае, ASCII) символ представлен как <U00xx> .

Итак, текст вроде этого:

 LC_TIME d_t_fmt "%a %d %b %Y %T %Z" d_fmt "%d-%m-%Y" t_fmt "%T" 

Должно быть:

 LC_TIME d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>" d_fmt "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059>" t_fmt "<U0025><U0054>" 

Таким образом, мне нужен сценарий командной строки (будь то bash, Python, Perl или что-то еще), который будет принимать входные данные, такие как %d-%m-%Y и преобразовать его в <U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059> .

Все символы входной строки будут символами ASCII (от 0x20 до 0x7F ), так что это на самом деле перекрестное преобразование «char-to-hex-string».

Может ли кто-нибудь помочь мне? Мои навыки в сценариях bash очень ограничены и еще хуже в Python.

Бонус для элегантных, объясненных решений.

Благодаря!

(кстати, это был бы «обратный» сценарий для моего предыдущего вопроса )

  • Запуск интерактивного Bash с помощью popen и выделенного TTY Python
  • Linux: вычислить один хэш для данной папки и содержимого?
  • Трубопровод к головке приводит к обрыву трубы в сценарии оболочки, вызванном из python
  • Как вызвать функцию / переменную скрипта оболочки из python?
  • Скрипт Python не работает в cron
  • Python и / или Perl VS bash
  • Отправить переменную среды bash обратно в ткань python
  • Как установить DMG-файл из командной строки?
  • 4 Solutions collect form web for “Скрипт для преобразования символов ASCII в нотацию Unicode «<Uxxx>»”

    Каждый символ с вводом файла

    Если вы хотите преобразовать каждый символ файла в представление юникода, то это будет простой однострочный

     while IFS= read -r -n1 c;do printf "<U%04X>" "'$c"; done < ./infile 

    Каждый символ на STDIN

    Если вы хотите создать unix-подобный инструмент, который преобразует входные данные на STDIN в unicode-подобный вывод, тогда используйте это:

     uni(){ c=$(cat); for((i=0;i<${#c};i++)); do printf "<U%04X>" "'${c:i:1}"; done; } 

    Доказательство концепции

     $ echo "abc" | uni <U0061><U0062><U0063> 

    Только символы между двойными кавычками

     #!/bin/bash flag=0 while IFS= read -r -n1 c; do if [[ "$c" == '"' ]]; then ((flag^=1)) printf "%c" "$c" elif [[ "$c" == $'\0' ]]; then echo elif ((flag)); then printf "<U%04X>" "'$c" else printf "%c" "$c" fi done < /path/to/infile 

    Доказательство концепции

     $ cat ./unime LC_TIME d_t_fmt "%a %d %b %Y %T %Z" d_fmt "%d-%m-%Y" t_fmt "%T" abday "Dom";"Seg";/ here is a string with "multiline quotes";/ $ ./uni.sh LC_TIME d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>" d_fmt "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0059>" t_fmt "<U0025><U0054>" abday "<U0044><U006F><U006D>";"<U0053><U0065><U0067>";/ here is a string with "<U006D><U0075><U006C><U0074><U0069><U006C><U0069><U006E><U0065> <U0071><U0075><U006F><U0074><U0065><U0073>";/ 

    объяснение

    Довольно просто на самом деле

    1. while IFS= read -r -n1 c; : Итерация по одному символу за один раз (через -n1 ) и сохранение символа в переменной c . Флаги IFS= и -r существуют, так что встроенный read не пытается выполнять разбиение на слова или интерпретировать escape-последовательности, соответственно.
    2. if [[ "$c" == '"' ]]; если текущий символ – это двойная кавычка
    3. ((flag^=1)) : инвертировать значение флага из 0-> 1 или 1-> 0
    4. elif [[ "$c" == $'\0' ]]; : Если текущий символ является NUL, тогда echo символ новой строки
    5. elif ((flag)) : Если флаг равен 1, выполните транслитерацию юникода
    6. printf "<U%04X>" "'$c" : волшебство, которое printf "<U%04X>" "'$c" юникод. Обратите внимание, что одинарная кавычка перед $c является обязательной, поскольку она сообщает printf что мы даем ей ASCII-представление числа.
    7. else printf "%c" "$c" : распечатать символ без транслитерации без юникода

    Использование Python

     #!/usr/bin/env python3.2 import sys text = sys.argv[1] encoded = "".join("<U{0:04X}>".format(ord(char)) for char in text) print(encoded) 

    Применение:

     $ python3 file.py "enter_input" <U0065><U006E><U0074><U0065><U0072><U005F><U0069><U006E><U0070><U0075><U0074> 

    (Тот же скрипт должен работать как для python 3.x, так и для 2.x. Просто измените версию в shebang на ту, что у вас есть.)

    Объяснение:

    1. Нам нужно импортировать модуль sys для чтения аргументов командной строки.

    2. Список sys.argv – это список всех аргументов командной строки. Запись [0] – это имя программы, запись [1] – это первый аргумент и т. Д.

    3. f(char) for char in text является выражением генератора . Он будет зацикливаться на каждый символ в text переменной, затем применить к нему функцию f и, наконец, собрать результат как ленивый список ( итерируемый ).

    4. ord(char) находит кодовую точку Unicode символа.

    5. "<U{0:04X}>".format(x) – это метод форматирования строк, который описывается именем. Строка формата принимает 1 входной сигнал x и форматирует в формат 04X , что означает начало-ноль, ширина-4, верхний регистр-шестнадцатеричный.

    6. "".join(it) объединяет все элементы в ленивом списке (iterable). "" Означает, что разделитель представляет собой пустую строку.

    7. print(encoded) записать строку, encoded в stdout.

    echo -n "aä" | ruby -KU -e '$<.chars{|c| print "<U"+"%04X"%c.unpack("U*")[0]+">"}; puts'

    Выходы <U0061><U00E4>

    -KU = $KCODE = "U"

    Решение сценария оболочки:

     #!/bin/sh while IFS= read -r -n1 c; do printf "<U%04X>" "'$c"; done 

    Это считывает стандартный ввод и выводит на стандартный вывод (при условии, что вы поместили скрипт в исполняемый файл toUnicode.sh ):

     > echo "hello" | toUnicode.sh <U0068><U0065><U006C><U006C><U006F><U0000> 

    Это печатает символ EOF ( <U0000> ), но вы можете изменить этот сценарий в соответствии с вашими потребностями, хотите ли вы читать ввод по одной строке за раз или обрезать его или изменить его другим способом.

    Python - лучший язык программирования в мире.