Как создать не-ascii файл, используя перенаправление с `sh -c`? - PullRequest
1 голос
/ 01 марта 2011

Та же команда: echo 1 > filename создает разные имена файлов:

$ sh -c 'echo $LANG >=с=.sh' && ls *.sh | od -c
0000000   = 321   =   .   s   h  \n
0000007

и

$ bash -c 'echo $LANG >=с=.bash' && ls *.bash | od -c
0000000   = 321 201   =   .   b   a   s   h  \n
0000012

Где с - это символ U+0441 - КИРИЧНОЕ МАЛЕНЬКОЕ ПИСЬМО ES . Понятно, что sh съедает второй байт в кодировке utf-8.

$ ls *sh
=?=.sh  =с=.bash

$LANG в обоих случаях:

$ cat *sh
en_US.utf8
en_US.utf8

sh связан с dash в моей системе:

$ apt-cache show dash | grep -i version
Version: 0.5.5.1-7ubuntu1

stty iutf8 установлено.

Есть ли какая-либо настройка, которая позволяет dash не манипулировать многобайтовыми символами?

Я не вижу упоминаний о кодировке символов в руководстве:

$ man dash | grep -i encoding
$ man dash | grep -Pi 'multi.*byte'

Обновление

Второй байт '\201' символа 'с' в кодировке utf-8 -127 как подписанный символ (или 129 как неподписанный символ) в C.

Поиск в исходном коде (apt-get source dash) для -127 приводит к:

src/parser.h:38:#define CTL_FIRST -127      /* first 'special' character */
src/parser.h:39:#define CTLESC -127     /* escape next character */

Поиск CTLESC приводит к rmescapes() макросам, которые приводят к следующий фрагмент из src/expand.c:expandarg():

/*
 * TODO - EXP_REDIR
 */
if (flag & EXP_FULL) {
    ifsbreakup(p, &exparg);
    *exparg.lastp = NULL;
    exparg.lastp = &exparg.list;
    expandmeta(exparg.list, flag);
} else {
    if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
        rmescapes(p);
    sp = (struct strlist *)stalloc(sizeof (struct strlist));
    sp->text = p;
    *exparg.lastp = sp;
    exparg.lastp = &sp->next;
}

TODO и XXX намекают на то, что более поздняя версия может Помогите. debian/dash.README.source указывает на:

$ git clone http://smarden.org/git/dash.git/
$ cd dash

Есть две ветви:

$ git br
* debian-sid
  release+patches

На debian-sid удаленный байт удален. На release+patches ветвь grep находит отсутствующий байт.

$ ./configure
$ make && rm *.dash -f; ./dash -c 'echo 1 >fсf.dash' && 
> ls *.dash | od -c | grep 201

git diff debian-sid...release+patches показывает, что rmescapes() было удалено в release-patches:

diff --git a/src/expand.c b/src/expand.c
index e4c4c8b..f2f964c 100644
--- a/src/expand.c
+++ b/src/expand.c
...
@@ -213,8 +210,6 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
                exparg.lastp = &exparg.list;
                expandmeta(exparg.list, flag);
        } else {
-               if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
-                       rmescapes(p);
                sp = (struct strlist *)stalloc(sizeof (struct strlist));
                sp->text = p;
                *exparg.lastp = sp;
@@ -412,7 +407,7 @@ lose:
 }

Неясно, будут ли эти изменения включены в dash 0.5.6.1 в Ubuntu.

На данный момент единственный способ сделать команду:

$ sh -c 'echo 1 >fсf.dash' &&  ls *.dash | od -c | grep 201

на работу - это перенастроить sh обратно на bash:

$ sudo dpkg-reconfigure dash

Есть ли другие альтернативы?

1 Ответ

1 голос
/ 02 марта 2011

Из нескольких оболочек (или версий), которые я пробовал, отказали только Dash и Busybox Ash.

$ for sh in bash2.05b bash3.2 bash4.0 bash4.1 bash4.2 dash zsh ksh pdksh mksh ash; do $sh -c 'locale > с.$0'; done
$ csh -c 'locale > с.csh'
$ fish -c 'locale > с.fish'
$ ls -1
?.ash
?.dash
с.bash2.05b
с.bash3.2
с.bash4.0
с.bash4.1
с.bash4.2
с.csh
с.fish
с.ksh
с.mksh
с.pdksh
с.zsh

Содержимое было одинаковым.

С man dash:

Включены только функции, обозначенные POSIX, плюс несколько расширений Беркли. в эту оболочку. Эта страница руководства не предназначена для обучения или полная спецификация оболочки.

POSIX говорит:

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

и

Широко-символьные коды для других символов определяются локалью и реализацией. ... POSIX.1-2008 не предоставляет средств для определения набора широких символов.

...