2014-12-26 2 views
4

Существует несколько способов, связанных с оболочкой, которые включают строку «unicode literal» в строке. Например, в Bash, цитируемый механизм расширения строк, $'', позволяет непосредственно вставлять невидимый символ: $'\u2620'.Каков наилучший способ вставки символа Unicode в сценарий оболочки POSIX?

Однако, если вы пытаетесь написать универсальные межплатформенные shell-скрипты (как правило, это может быть усечено до «работает в Bash, Zsh и Dash.»), Это не переносная функция.

я могу переносимый достичь чего-либо в таблице ASCII (восьмеричный номер-пространство) с конструкцией, как следующее:

WHAT_A_CHARACTER="$(printf '\036')" 

... Однако, POSIX/черточка printf поддерживает только восьмеричные побеги.

Я также, очевидно, может достичь полного пространства Unicode с помощью сельского хозяйства задачу, чтобы в более полной программной среде:

OH_CAPTAIN_MY_CAPTAIN="$(ruby -e 'print "\u2388"')" 
TAKE_ME_OUT_TONIGHT="$(node -e 'console.log("\u266C")')" 

Итак: что лучший способ для кодирования такого символа в раковине-скрипт, что:

  1. Работает в dash, bash и zsh,
  2. показывает шестнадцатеричное кодирование в элемент кода, кода
  3. не зависит от конкретной кодировки строки (т.е. не путем кодирования байтов UTF-8 в восьмеричном)
  4. и, наконец, не требует вызова любого «тяжелого» интерпретатора. (Скажем, менее 0,01 с выполнения.)
+1

Без 2, вы можете, конечно, иметь свой персонаж дословно в источнике сценария, например, 'printf '⎈ ♬ \ n''. Если у вас есть достойный редактор, наведите курсор на него, он должен показать код; и вы также сможете ввести его (например, Ctrl + Shift + u 2388). Я не понимаю, почему 2 действительно проблема. –

+0

@gniourf_gniourf проблема с 2 в основном состоит в том, что она * требует * достойного редактора. Существует множество ситуаций, когда я хочу, чтобы мой исходный код был доступен для тех, кто не имеет такой роскоши. Наличие специальных символов, которые имеют решающее значение для функции программы, закодированной доступным способом, открывает разработку источника для более крупной группы-участников. Это не всегда * (или даже часто!) Беспокойство, но иногда это стоит учитывать. ;) – ELLIOTTCABLE

+0

@gniourf_gniourf (существует множество ситуаций, даже в волнении 2015 года, когда дословные документы, закодированные в Юникоде, будут искажены конвейерами, предполагающими простой ASCII или ISO-8859-1. Это печальная правда.) – ELLIOTTCABLE

ответ

6

Если у вас есть Gnu printf установлен (это в пакете DEBiAN coreutils), то вы можете использовать его независимо от того, какую оболочку вы используете, избегая встроенной оболочки:

env printf '\u2388\n' 

Здесь я использую Posix-стандартный env команду, чтобы избежать использования printf встроенной команды, но если вы не знаете, где printf это вы можете сделать это напрямую, используя полный, путь, например

/usr/bin/printf '\u2388\n' 

Если ваш внешний printf и встроенный в ваш корпус корпус printf используют только стандарт Posix, вам нужно работать усерднее. Одна из возможностей заключается в использовании iconv для перевода на UTF-8, но, хотя стандарт Posix требует, чтобы был командой iconv, он никоим образом не предписывает, как названы стандартные кодировки.Я думаю, что следующее будет работать на большинстве Posix-совместимых платформ, но количество подоболочек созданных может быть достаточно, чтобы сделать его менее эффективным, чем «тяжелый» сценарий переводчик:

printf $(printf '\\%o' $(printf %08x 0x2388 | sed 's/../0x& /g')) | 
iconv -f UTF-32BE -t UTF-8 

выше использует printf встроенной команду, чтобы заставить значение шестнадцатеричного кодового слова должно быть 8 шестнадцатеричных цифр, затем sed, чтобы переписать их как 4 шестнадцатеричных константы, затем printf снова, чтобы изменить шестнадцатеричные константы в восьмеричную нотацию и, наконец, еще один printf, чтобы интерпретировать восьмеричные постоянные символа в четырехбайтную последовательность, которая может подаваться в iconv в качестве широкоформатного UTF-32. (Это было бы проще с printf, который признает \x экранирующих кодов, но Posix не требует, чтобы и dash не реализует его.)

Вы можете использовать строку без изменений на печать более одного символа, до тех пор, как вы предоставить кодовые Unicode (как целочисленные константы) для каждого из них (например, выполненных в dash):

$ printf $(printf '\\%o' $(printf %08x 0x2388 0x266c 0xA | 
>       sed 's/../0x& /g')) | 
> iconv -f UTF-32BE -t UTF-8 
⎈♬ 
$ 

Примечание: Как Geoff Никсон упоминает в комментариях, рыба оболочка (которая нигде близко к Posix, и, насколько я вижу, не имеет стремления к соответствию) будет жаловаться на неупорядоченные %08x аргумент формата printf, так как он ожидает, что слова, начинающиеся с %, будут выполняться с помощью заданий. Поэтому, если вы используете рыбу, добавьте кавычки в аргумент формата.

+2

Команда ['command'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html) предназначена для той цели, для которой вы используете' env'. –

+0

@JonathanLeffler: 'command' избегает функций оболочки, а не встроенных оболочек. (Posix: «Если имя_компьютера совпадает с именем одной из специальных встроенных утилит, специальные свойства в списке перечислений в начале специальных встроенных утилит не должны возникать.»; 'Man dash': «Выполнить указанную команду, но игнорировать функции оболочки при поиске».) – rici

+1

OK - вид. Я вижу, во что ты едешь. Строго говоря, в соответствии с техническими условиями для POSIX 'printf' не является встроенной оболочкой: командами, которые являются специальными встроенными модулями, являются:' break', 'colon',' continue', 'dot',' eval ',' exec', 'exit',' export', 'readonly',' return', 'set',' shift', 'times',' trap', 'unset' (где' colon' и 'dot' написаны ':' и '.' соответственно). То, что оболочка должна делать с 'printf', это« не выполнять встроенный »- независимо от того, выполняет ли она что-то другое, является спорным. В качестве примера, в Bash, 'command cd' по-прежнему удается изменить каталог оболочки. –

-3

я бы с

echo -e "\xc3\xb6" 

не проверить его:

~ $ echo -e "\xc3\xb6" 
ö 
~ $ echo -n ö | hexdump 
0000000 b6c3         
0000002 
+1

Обратите внимание, что, например, '\ u2388 ≠ \ x23 \ x88'. Скорее, '\ u2388 = \ xe2 \ x8e \ x88 \ x00'. –

+2

Это не работает в 'dash'. Кроме того, он, вероятно, терпит неудачу в требовании (3): «не зависит от конкретной кодировки строки (т. Е. Не путем кодирования байтов UTF-8 в восьмеричном)». (Он требует кодирования байтов UTF-8, хотя и в шестнадцатеричном виде, поэтому он скрывает исходный код Unicode.) – rici

+1

Кроме того, соблюдение '-e' как чего-либо, кроме строки, подлежащей печати, нарушает спецификацию POSIX для' echo' (не " не гарантируется ", но фактически" нарушает "). '-n', а строки с обратными косыми чертами - это реализация запрещенных расширений XSI, тогда как' -e' вообще не разрешается. См. Http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html - включая раздел ПРИМЕНЕНИЕ ИСПОЛЬЗОВАНИЯ стандарта, который предлагает использовать 'printf' вместо этого. –