Кодирование символов в Linux (bash script)

Как то мне снова понадобилось кодировать символы в их HTML сущности. Ситуация крайне распространенная — нужно было вставить пример кода с Markdown разметкой, да так, чтобы он не транслировался в HTML. Вариант только один — вместо символа ~ (тильды) необходимо вставить HTML сущность этого символа. Можно было просто погуглить и найти код для этого символа.. но, я решил автоматизировать процесс конвертирования символов с помощью bash-скрипта и горячих клавиш.

Преобразовать базовые ASCII символы оказалось довольно просто:

echo -n "<" | recode ascii..html     # на выходе &lt;
echo -n "&lt;" | recode html..ascii  # на выходе <
echo "&#126;" | recode ascii..html   # на выходе ~, т.к. это не служебный символ разметки HTML

Но ту же тильду таким образом конвертировать — ну никак, поскольку она как бы не является частью HTML разметки.
Но мы то знаем, что все символы в HTML можно вставить через их десятичный или шестнадцатеричный код. Например тильда в DEC=&#126; или HEX’формате — &#x7e;. Алиас, не всегда соответствует отображаемому символу: &tilde; = ˜ = ~, поэтому нужно указывать именно код символа.

Опишу утилиты и команды, которые позволят выдернуть код любого символа..

Этот вариант пригодится, если необходимо получить алиас (Description) символа, а не его код:

echo -n "~" | recode us..dump
# Результат:
UCS2   Mne   Description
007E   '?    tilde

Документация по recode

Hexdump позволяет получить HEX любой строки, и преобразовать в нужный формат (синтаксис описания формата мне показался очень мудреным — регулярки отдыхают)):

echo -n "~" | hexdump -ve '1/1 "%.2x"'

Но лучшим вариантом я считаю ф-цию printf:

printf '&#%d;'   "'~" # Десятичное представление &#126;
printf '&#x%x;'  "'~" # Шестнадцатеричное представление &#x7e;

В итоге у меня получился скрипт, который конвертирует символы в их HTML сущности. Местами не очень изящно, но свою работу (вернее мою) он делает. Сохраняете, даете права на исполнение, вешаете на хоткей. Все.

Рад продуктивной критике.

#!/bin/bash

# Convert ASCII to HTML entity
# Hotkey    Ctrl + Alt + ]
# Require:
# xsel, xdotool
#
# Логика работы скрипта
# После перекодирования строки в HTML сущность утилитой recode 
# результирующая строка не изменилась и выделен только один символ - 
# тогда скрипт кодирует символ в HEX сущность.

# Запомним что было в буфере
buffer="$(xsel -b)"

# Получить выделенный текст
selection="$(xsel)"

# Преобразуем ASCII строку в HTML сущности и вернем результат в буфер для вставки
echo -n "$selection" | recode ascii..html | xsel -b -i

# Если recode не перекодировал один символ - кодируем его в HEX представление
if [ -n "$(xsel -b)"] || [ "$(xsel -b)" == "$selection" ]; then
  length=${#selection}
  if [ $length -eq 1 ]; then
    printf '&#%d;' "'$selection" | xsel -b -i   # DEC
    #printf '&#x%x;' "'$selection" | xsel -b -i # HEX
  fi
fi

# Если не успевает отработать вставка из буфера - нужна пауза
sleep 0.30

# Вставим содержимое из буфера (результат преобразования) через триггер нажатия Ctrl + V
xdotool key 37+55 #xdotool key Control_L+v

# Вернем в буфер то, что было в нем изначально
if [ "$buffer" ]; then
  echo -n "$buffer" | xsel -b -i
fi