Как правильно экранировать символы юникода в bash - PullRequest
7 голосов
/ 18 августа 2011

У меня есть специальный метод для моего приглашения bash, скажем, он выглядит следующим образом:

CHAR="༇ "
my_function="
    prompt=\" \[\$CHAR\]\"
    echo -e \$prompt"

PS1="\$(${my_function}) \$ "

Чтобы объяснить вышесказанное, я строю свой запрос bash, выполняя функцию, хранящуюся в строке,которое было принято в результате этого вопроса .Давайте притворимся, что все работает нормально, потому что это происходит, за исключением случаев, когда задействованы символы юникода

Я пытаюсь найти правильный способ экранирования символа юникода, потому что сейчас он портится с длиной строки bash.Простой способ проверить, не сломана ли она, - набрать длинную команду, выполнить ее, нажать CTRL-R и набрать, чтобы найти ее, а затем нажать CTRL-A CTRL-E, чтобы перейти к началу / концу строки.Если текст искажен, значит, он не работает.

Я пробовал несколько вещей, чтобы правильно экранировать символ юникода в строке функции, но, похоже, ничего не работает.

Специальные символы, подобные этой работе:

COLOR_BLUE=$(tput sgr0 && tput setaf 6)

my_function="
    prompt="\\[\$COLOR_BLUE\\] \"
    echo -e \$prompt"

Именно по этой причине я сделал подсказку строкой функции.Эта escape-последовательность НЕ связывается с длиной строки, это просто символ Unicode.

Ответы [ 3 ]

3 голосов
/ 19 августа 2011

Последовательность \[...\] говорит о полном игнорировании этой части строки, что полезно, когда в вашем приглашении содержится последовательность нулевой длины, например управляющая последовательность, которая изменяет цвет текста или, например, строку заголовка.Но в этом случае вы печатаете символ, поэтому его длина не равна нулю.Возможно, вы могли бы обойти это, скажем, используя escape-последовательность no-op, чтобы обмануть Bash в расчете правильной длины строки, но это звучит так, как будто это безумие.

Правильное решение будет для линиирасчет длины в Bash для правильного использования UTF-8 (или любой другой кодировки Unicode, которую вы используете).Хм, вы пробовали без последовательности \[...\]?

Редактировать: Следующее реализует решение, которое я предлагаю в комментариях ниже.Положение курсора сохраняется, затем печатаются два пробела за пределами \[...\], затем восстанавливается положение курсора, а символ Unicode печатается поверх двух пробелов.Это предполагает фиксированную ширину шрифта с двойной шириной для символа Unicode.

PS1='\['"`tput sc`"'\]  \['"`tput rc`"'༇ \] \$ '

По крайней мере в терминале OSX, выпуск Bash 3.2.17 (1), это проходит краткое тестирование [sic].

В интересах прозрачности и разборчивости я проигнорировал требование иметь функциональность подсказки внутри функции и цветовое кодирование;это просто изменяет подсказку на символ, пробел, подсказку доллара, пробел.Приспособьтесь к своим более сложным потребностям.

2 голосов
/ 23 августа 2011

@ tripleee выигрывает это, публикуя окончательное решение здесь, потому что писать код в комментариях очень сложно:

CHAR="༇"
my_function="
    prompt=\" \\[`tput sc`\\]  \\[`tput rc`\\]\\[\$CHAR\\] \"
    echo -e \$prompt"

PS1="\$(${my_function}) \$ "

Хитрость, указанная в ссылке @ tripleee, заключается в использовании команд tput sc и tput rc, которые сохраняют, а затем восстанавливают позицию курсора. Код эффективно сохраняет позицию курсора, печатает два пробела по ширине, восстанавливает позицию курсора до пробелов, а затем печатает специальный символ так, чтобы ширина строки была из двух пробелов, а не символа.

0 голосов
/ 19 августа 2011

(Не ответ на вашу проблему, но некоторые указания и общий опыт, связанный с вашей проблемой.)

Я вижу поведение, которое вы описываете при редактировании строки cmd (Ctrl-R, ... Cntrl-A Ctrl-E ...) все время, даже без символов Юникода.

На одном рабочем месте я потратил время на то, чтобы выяснить разницу между терминалами, интерпретирующими настройку TERM против определения TERM, используемого ОС (ну, я полагаю, stty).

СЕЙЧАС, когда у меня возникла эта проблема, я выхожу из своей текущей попытки отредактировать строку, снова вывести строку вверх, а затем сразу же перейти в режим 'vi', который открывает редактор vi.(нажмите только символ 'v', верно?).Вся простота использования полноценного сеанса vi;зачем идти с меньшими затратами; -)?

Снова глядя на описание вашей проблемы, когда вы говорите

my_function="
    prompt=\" \[\$CHAR\]\"
    echo -e \$prompt"

Это просто определение строки, верно?и я предполагаю, что вы упростили определение проблемы, предполагая, что это вывод вашей my_function.Кажется весьма вероятным, что на этапах создания определения функции вызов функции И с использованием возвращаемых значений предоставляет множество возможностей для цитирования оболочки, чтобы не работать так, как вы этого хотите.

Если вы редактируете свойвопрос о том, чтобы включить определение my_function и его полное использование (сводя вашу функцию к тому, что является причиной проблемы), другим также может быть легче помочь с этим.Наконец, вы регулярно используете set -vx?Это может помочь показать, как / wnen / что из расширений переменных, вы можете найти что-то там.

Если все это не сработает, посмотрите на termcap Orielly & terminfo .Вам может понадобиться просмотреть справочную страницу для ваших локальных систем stty и связанных с ними командных ключей, и вы можете преуспеть в поиске групп пользователей, специфичных для вашей системы Linux (я предполагаю, что вы используете вариант Linux).

Надеюсь, это поможет.

...