Проблема с некоторыми программами из coreutios в Debian (и не только) (В Red Hat их нет)

Knoppix

Модераторы: Warderer, Модераторы разделов

Ответить
MiK13
Сообщения: 1164
ОС: Linux Debian

Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение MiK13 »

Я уже как-то писал о этой проблеме с программами expand и fold. Потом обнаружил её в программе uniq и совсем недавно в программеcut. (В программе wc всё нормально).
А именно: эти программы читают файлы не по буквам, а по байтам. Что видно из следующего примера.
Но перед этим скажу, что я эти программы взял из CentOS и записал в ~/bin, так что по умолчанию вызываются они.

Shell

mik13@md5:~$ echo -e "dddddd\nвввввв" | /bin/cut -c1-4
dddd
вв
mik13@md5:~$ echo -e "dddddd\nвввввв" | cut -c1-4
dddd
вввв
mik13@md5:~$ echo -e "dddddd\nвввввв" | cut -b1-4
dddd
вв
То есть дебиановская программа вырезает не буквы (characters, с первой по четвёртую) а байты. Так же, как и программа из CentOS, если ей указать опцию -b. А если указать опцию -c, то она вырежет именно буквы. Даже если это будут знаки, которые в UTF-8 требуют 4 байта:

Shell

mik13@md5:~$ echo -e "🤧🤧🤧🤧🤧🤧🤧🤧\ndddddd\nвввввв" | cut --characters=1-4
🤧🤧🤧🤧
dddd
вввв
mik13@md5:~$ echo -e "🤧🤧🤧🤧🤧🤧🤧🤧\ndddddd\nвввввв" | /bin/cut --characters=1-4
🤧
dddd
вв
Аналогичная проблема и с программой expand. Заменяя знаки табуляции на пробелы, она рассчитывает позицию окончания табуляции исходя из числа не знаков, а байтов.

Shell

mik13@md5:~$ echo -e "ыыы\tввв" | expand
ыыы ввв
mik13@md5:~$ echo -e "ыыы\tввв" | /bin/expand
ыыы ввв
Причём такая же проблема есть и в Мандриве.
Сначала я подумал, что просто разработчики этих программ не подумали о том, что знаки могут быть не только однобайтовыми. Но, ведь в RHEL и CentOS (наверняка и в Федоре) это сделано корректно.
Чем это можно объяснить?
Может быть есть и другие программы, в которых это не учитывается?
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Bizdelnick »

MiK13 писал:
06.09.2021 21:53
Но, ведь в RHEL и CentOS (наверняка и в Федоре) это сделано корректно.
Чем это можно объяснить?
Лезете в федоровские исходники, обнаруживаете пачку патчей:
https://src.fedoraproject.org/rpms/coreutils/blob/rawhide/f/coreutils.spec#_91-106
Можно в ченжлоге поискать по слову multibyte, сколько в этих патчах было ошибок, прикинуть, сколько их, вероятно, ещё осталось, и подумать, так ли оно надо.
А ещё можно поискать, что есть в багтрекере coreutils: https://debbugs.gnu.org/cgi/pkgreport.cgi?package=coreutils;include=subject%3Amultibyte
TL;DR: проблема давно известна, в разных дистрибутивах используются патчи разного радиуса кривизны, но довести их до приличного вида и отправить в апстрим никто так и не сподобился.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
MiK13
Сообщения: 1164
ОС: Linux Debian

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение MiK13 »

Bizdelnick писал:
06.09.2021 22:41
Лезете в федоровские исходники, обнаруживаете пачку патчей:
https://src.fedoraproject.org/rpms/coreutils/blob/rawhide/f/coreutils.spec#_91-106
Можно в ченжлоге поискать по слову multibyte, сколько в этих патчах было ошибок, прикинуть, сколько их, вероятно, ещё осталось, и подумать, так ли оно надо.
Раз у меня возникла такая потребность (работать с мультибайтовыми символами), значит она существует. И, как я понял, не только у меня.
Bizdelnick писал:
06.09.2021 22:41
проблема давно известна, в разных дистрибутивах используются патчи разного радиуса кривизны, но довести их до приличного вида и отправить в апстрим никто так и не сподобился.
А насколько сложно просто переписать заново эти программы, заменив char на wchar_t, а функции типа fgetc и fgets на, соответственно, fgetwc и fgetws?
Или, хотя бы сделать варианты этих программ, добавив к имени букву 'w'.
В wc это, ведь, сделано.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Bizdelnick »

MiK13 писал:
10.09.2021 14:55
Раз у меня возникла такая потребность (работать с мультибайтовыми символами), значит она существует. И, как я понял, не только у меня.
Я не про потребность как таковую, а про конкретную реализацию.
MiK13 писал:
10.09.2021 14:55
А насколько сложно просто переписать заново эти программы, заменив char на wchar_t, а функции типа fgetc и fgets на, соответственно, fgetwc и fgetws?
Элементарно, только правильно работать они не будут. Многобайтные и «широкие» символы — это разные вещи (см. mbrtowc(3), wctomb(3) и прочие функции mb*).
MiK13 писал:
10.09.2021 14:55
В wc это, ведь, сделано.
В wc проще, там всё решается одним циклом с mbrlen (по идее, в код не смотрел).
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
MiK13
Сообщения: 1164
ОС: Linux Debian

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение MiK13 »

Bizdelnick писал:
10.09.2021 16:16
Элементарно, только правильно работать они не будут.
А какие могут быть проблемы?
Bizdelnick писал:
10.09.2021 16:16
Многобайтные и «широкие» символы — это разные вещи
А что понимается под «широкими»?
Я понимаю, что это те, которые имеют тип wchar_t. Правда, есть ещё те, которые в моноширинных шрифтах занимают две позиции. Но есть там и символы нулевой длины. Вряд ли символы двойной ширины можно понимать под «широкими».
Bizdelnick писал:
10.09.2021 16:16
(см. mbrtowc(3), wctomb(3) и прочие функции mb*).
Поразбирался с функцией mbrtowc, По-моему, она в таких программах, как expand, cut, uniq и подобных не нужна. Они, ведь, работают с печатными символами. И там будет достаточно функций типа fgetwc. А вот для реализации этих функций, а также форматов %lc и %ls и нужны функции mb*. Но это уже задачи более низкого уровня
Bizdelnick писал:
10.09.2021 16:16
MiK13 писал:
10.09.2021 14:55
В wc это, ведь, сделано.
В wc проще, там всё решается одним циклом с mbrlen (по идее, в код не смотрел).
Вот в wc, на мой взгляд, сложнее. Из-за наличия опций как -c, так и -m, которые могут быть использованы совместно. Поэтому там надо сначала прочитать данные из файла, и только потом их анализировать как по байтам, так и по символам. Да ещё, если файл не может быть прочитан за один раз, нужно правильно сделать стыковку.
Хотя cut тоже имеет опции и -b и -c, но я пока не могу представить, зачем может понадобиться их совместное использование.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Bizdelnick »

MiK13 писал:
11.09.2021 00:17
А какие могут быть проблемы?
Ну какая может быть проблема, если Вы станете читать как wchar_t то, что не является wchar_t? Фигня получится.
MiK13 писал:
11.09.2021 00:17
в wc, на мой взгляд, сложнее. Из-за наличия опций как -c, так и -m, которые могут быть использованы совместно. Поэтому там надо сначала прочитать данные из файла, и только потом их анализировать как по байтам, так и по символам. Да ещё, если файл не может быть прочитан за один раз, нужно правильно сделать стыковку.
Эта логика там уже реализована для сочетания других опций, не вижу принципиально новых сложностей.
Добавлено (01:11):
MiK13 писал:
11.09.2021 00:17
Поразбирался с функцией mbrtowc, По-моему, она в таких программах, как expand, cut, uniq и подобных не нужна. Они, ведь, работают с печатными символами. И там будет достаточно функций типа fgetwc. А вот для реализации этих функций, а также форматов %lc и %ls и нужны функции mb*. Но это уже задачи более низкого уровня
Впрочем, может быть и так…
man fgetwc писал(а):In the absence of additional information passed to the fopen(3) call, it is reasonable to expect that fgetwc() will actually read a multibyte sequence from the stream and then convert it to a wide character.
Хотя что-то смущает меня формулировка «it is reasonable to expect».
Добавлено (01:24):
Но в любом случае использование wchar_t — не самый лучший вариант в плане переносимости. Он ведь может и 16 бит шириной быть на некоторых платформах (по стандарту — и 8, хотя на практике о таком не слышал). Вроде как, даже на винде такой. В него не всё влезет.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
MiK13
Сообщения: 1164
ОС: Linux Debian

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение MiK13 »

Bizdelnick писал:
11.09.2021 01:07
MiK13 писал:
11.09.2021 00:17
А какие могут быть проблемы?
Ну какая может быть проблема, если Вы станете читать как wchar_t то, что не является wchar_t? Фигня получится.
Над этим я ещё подумаю.
Bizdelnick писал:
11.09.2021 01:07
man fgetwc писал(а):In the absence of additional information passed to the fopen(3) call, it is reasonable to expect that fgetwc() will actually read a multibyte sequence from the stream and then convert it to a wide character.
Хотя что-то смущает меня формулировка «it is reasonable to expect».
Написал простую программу. С кодом, подобным этому:

Код: Выделить всё

int ws[256],*ps;
int main() {
  setlocale(LC_ALL,"");
  while((ps=fgetws(ws,250,stdin))) {
    while(*ps) fputwc(*ps++,stdout);
    fputws(ws,stdout);
  }
Введённая с терминала строка выводится два раза.
Но обнаружил странный эффект.
Впечатление, что функции fputwc и fputws несовместимы с функцией printf
То есть если я что-то выведу по printf (fprintf), то ни fputwc, ни fputws выводить не будут.
А если я выведу по fputwc, то printf ничего не будет выводить.
Bizdelnick писал:
11.09.2021 01:07
Добавлено (11.09.2021 01:24):
Но в любом случае использование wchar_t — не самый лучший вариант в плане переносимости. Он ведь может и 16 бит шириной быть на некоторых платформах (по стандарту — и 8, хотя на практике о таком не слышал). Вроде как, даже на винде такой. В него не всё влезет.
Тут согласен. Я когда-то даже сам удивился, что wchar_t это 4 байта, а не 2 (вроде так было в винде). Но, посмотрев файл UTF-8.gz, увидел, что там есть знаки с кодом, который не умещается в 2 байта. В частности L'🤧'.
Но, с другой стороны, полной совместимости нет даже в пределах одной системы.
long в i386 занимает 4 байта, а в amd64 8.
long double соответственно 12 и 16. Хотя реально 10. Как extended в Pascal. А в SUN это реально 16.
В Raspbian sizeof(long double) показал 8 (уточню странслировав в Debian)
Спасибо сказали:
Aliech
Сообщения: 952
Статус: дилетант широкого профиля
ОС: Gentoo arm64 musl hardened
Контактная информация:

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Aliech »

MiK13 писал:
16.09.2021 01:43
Но, с другой стороны, полной совместимости нет даже в пределах одной системы.
long в i386 занимает 4 байта, а в amd64 8.
long double соответственно 12 и 16. Хотя реально 10. Как extended в Pascal. А в SUN это реально 16.
В Raspbian sizeof(long double) показал 8 (уточню странслировав в Debian)
В свежих C'ях (ну как свежих? C99) для переносимости ввели типы с указанием "битности".
https://ru.wikipedia.org/wiki/Stdint.h
С уважением,
Павел Алиев
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Bizdelnick »

Aliech писал:
16.09.2021 11:37
В свежих C'ях (ну как свежих? C99) для переносимости ввели типы с указанием "битности".
Работе с wide character string они не помогут.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Aliech
Сообщения: 952
Статус: дилетант широкого профиля
ОС: Gentoo arm64 musl hardened
Контактная информация:

Re: Проблема с некоторыми программами из coreutios в Debian (и не только)

Сообщение Aliech »

Bizdelnick писал:
16.09.2021 12:27
Работе с wide character string они не помогут.
Ну так я подобного и не обещал ;)
Но ситуацию с числовыми типами и разными системами/архитектурами они позволяют в какой-то мере упростить.
С уважением,
Павел Алиев
Спасибо сказали:
Ответить