LINUX.ORG.RU

bash первый символ переменной в UTF 8


0

1

Подскажите, как достать первый символ переменной, заданной в кодировке UTF-8? Плюс, есть необходимость, замены первого символа в данной строке.
Читал здесь: bash первый символ переменной, ни один совет не помогает. Суть в чём: авторизация PAM. Прописал в common-auth автозагрузку моего скрипта. Если в нём просто указать echo $PAM_USER >> /home/user/log, то в етом файле имя пользователя отображается нормально. Но если попробовать, к примеру, echo `echo «$PAM_USER» | sed 's/^\(.\).*/\1/'` >> /home/user/log, то в логе отображается первый байт UTF-символа. Получается, метод не определяет кодировку, а просто выбирает первый байт входящей строки. Как побороть?

[~] >> echo толсто | sed 's/^\(.\).*/\1/'
т

Может, кому-то нужно починить локаль? :)

GotF ★★★★★
()

abr_linux> echo `echo «$PAM_USER» | sed 's/^\(.\).*/\1/'` >> /home/user/log

настрой локаль. У тебя эта строка запускается с локалью отличной от LANG=??_??.UTF-8

sdio ★★★★★
()
Ответ на: комментарий от sdio

Строка запускается из /etc/pam.d/common-auth, конкретно из строки «auth pam_exec.so /usr/bin/myscript.sh». Получается, PAM не поддерживает utf-8?

abr_linux
() автор топика
Ответ на: комментарий от GotF

Вывод $(locale) такой:
LANG= LC_CTYPE=«POSIX» LC_NUMERIC=«POSIX» LC_TIME=«POSIX» LC_COLLATE=«POSIX» LC_MONETARY=«POSIX» LC_MESSAGES=«POSIX» LC_PAPER=«POSIX» LC_NAME=«POSIX» LC_ADDRESS=«POSIX» LC_TELEPHONE=«POSIX» LC_MEASUREMENT=«POSIX» LC_IDENTIFICATION=«POSIX» LC_ALL=

Придумать можно будет что-нть?

abr_linux
() автор топика
Ответ на: комментарий от GotF

Спасибо! Само то. Правда, я LANG поставил, работает как задумано :)

abr_linux
() автор топика
Ответ на: комментарий от abr_linux

использовать UTF-8 с правами рута - опасно. Т.ч. лучше так не делайте - злоумышленник может заставить выполнятся свой вредоносный код.

drBatty ★★
()
Ответ на: комментарий от abr_linux

Вот простой пример: нам надо отсечь всё, что лежит после «|»

$ echo -e "тест|вредоносный код" | sed 's/|.*//'
тест

Как видите, всё прекрасно работает... Однако:

$ echo -e "тест|\xD1вредоносный код" | sed 's/|.*//'
тест?вредоносный код

Ну вот... Вредоносный код успешно проник сквозь фильтр :-(

Это касается любых ЯП. Беда в том, что многие свято верят, что точка совпадает с любым символом, и это так. Но в UTF-8 есть и НЕСИМВОЛЫ, с ними точка не совпадает. Видимо потому при входе в аккаунт рута включается LC_ALL=C, там точка совпадает с любым байтом и символом.

drBatty ★★
()
Ответ на: комментарий от drBatty

В UTF-8 вроде ж не так много спецсимволов, которые находятся в начале составного utf-символа. Их можно наряду с точкой в квадратных скобках задавать.
А вобще, какие предложения у вас могут быть? Задача такая: пользователи в AD на русском (и начальство не волнует, что ето не труЪ-правильно), а мне необходимо в файле настроек remmina создать новое подключение с именем пользователя и чтобы у него первая буква в фамилии была большой. По-умолчанию, pam+samba передаёт имя пользователя только мелкими буквами.

abr_linux
() автор топика
Ответ на: комментарий от abr_linux

В UTF-8 вроде ж не так много спецсимволов, которые находятся в начале составного utf-символа.

а злоумышленнику достаточно всего одного несимвола.

А вобще, какие предложения у вас могут быть? Задача такая: пользователи в AD на русском (и начальство не волнует, что ето не труЪ-правильно), а мне необходимо в файле настроек remmina создать новое подключение с именем пользователя и чтобы у него первая буква в фамилии была большой. По-умолчанию, pam+samba передаёт имя пользователя только мелкими буквами.

всё просто:

#!/bin/sed -f
s/а/А/
s/б/Б/
s/в/В/
# и так далее весь алфавит
сохраните этот файл, дайте ему права исполнения, и он будет менять первую русскую букву в UTF-8 (сохраняйте скрипт именно в UTF-8!), при любой локали - для sed при LC_ALL=C буква ф это просто два байта, которые будут заменены на другие два байта, которые дадут Ф.

Я именно так и делаю. Это конечно не так элегантно как sed 's/./\U&/' но работает.

drBatty ★★
()
Ответ на: комментарий от abr_linux

>В UTF-8 вроде ж не так много спецсимволов, которые находятся в начале составного utf-символа. Их можно наряду с точкой в квадратных скобках задавать.

вы не понимаете, \xD1 это вовсе не «спецсимвол в UTF-8», в UTF-8 вообще нет такого символа, и он ни с чем не совпадает (при локали UTF-8). функция glibc просто выдаёт несовпадение, проглатывает этот несимвол и бежит проверять дальше. И это нормальное, документированное поведение. Из за этого пришлось даже ввести в sed новую команду z, которая очищает внутренний буфер. До распространения UTF-8 команда z была ненужна, т.к. можно было просто заменить все символы на пустую строку, но в UTF-8 это сломалось.

drBatty ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.