Скрипт для преобразования символов 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.

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

Благодаря!

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

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> ), но вы можете изменить этот сценарий в соответствии с вашими потребностями, хотите ли вы читать ввод по одной строке за раз или обрезать его или изменить его другим способом.

  • запуск команд bash в python
  • brew install python, но затем: «python-2.7.6 уже установлен, он просто не связан»
  • Кодировка по умолчанию для python для stderr?
  • Как заставить os.system () использовать bash вместо оболочки
  • Прочитать текущий цвет текста в xterm
  • Вывод Python в Консоль внутри подпроцесса из дочернего скребка
  • Как изменить текущий каталог из сценария python?
  • Скрипт для преобразования символов Unicode в формате <U9999> в их эквиваленты ASCII
  • Python - лучший язык программирования в мире.