Как кодировать разные типы данных для STDOUT, чтобы STDIN мог определить, что есть что? [закрыто]

Pude construir con éxito gcc -4.9.0. de esta pregunta:https://stackoverflow.com/q/11502045/1363169; Vi esta respuestahttps://stackoverflow.com/a/16215539/1363169que fue particularmente útil para esta solución.

A continuación se detallan las medidas adoptadas

1. Descargue los archivos necesarios. Para construir gcc, se requieren tres dependencias:

a. Biblioteca aritmética de precisión múltiple GNU (GMP)-Usé gmp -6.0.0

b. Flotante de precisión múltiple GNU -Point Reliably (MPFR)-Utilicé mpfr -3.1.2

c. Se utilizó GNU MPC -mpc -1.0.2.

Todo esto se puede descargar desde aquí :https://ftp.gnu.org/pub/gnu/, también puede descargar gcc desde uno de sus sitios espejo aquíhttps://gcc.gnu.org/mirrors.html

2. Declare sus variables

    gccver=4.9.0

    gmpver=6.0.0

    mpfrver=3.1.2

    mpcver=1.0.2

    # where you downloaded source packages

    pkgdir=$HOME

    # where gcc will be built
    rootdir=$HOME/gcc-tmp


    # where gcc will be installed 
    prefix=/opt/gcc-${gccver}

    # the languages you want gcc to support
    langs=c,c++

3. Cree un nuevo directorio donde desee guardar las fuentes y extraiga las fuentes allí

     mkdir ${rootdir}

     cd ${rootdir}


    gzip -dc ${pkgdir}/gcc-${gccver}.tar.gz | tar xvf - 
    gzip -dc ${pkgdir}/gcc-${gmpver}.tar.gz | tar xvf - 
    gzip -dc ${pkgdir}/gcc-${mpfrver}.tar.gz | tar xvf - 
    gzip -dc ${pkgdir}/gcc-${mpcver}.tar.gz | tar xvf - 

NOTA :si tiene un problema como un error de suma de comprobación al extraer el archivo, consulte:Cómo extraer correctamente un.tar.gz con md5.sum en solaris 10 para obtener soluciones.

4. Ahora, mueva las fuentes extraídas al directorio fuente gcc

    mv gmp-${gmpver}   gcc-${gccver}/gmp

    mv mpfr-${mpfrver} gcc-${gccver}/mpfr

    mv mpc-${mpcver}   gcc-${gccver}/mpc

5. Cree un directorio de compilación y cámbielo

    mkdir objdir

    cd objdir

6. Ahora configure el gcc:

    ${rootdir}/gcc-${gccver}/configure --prefix=${prefix}   --enable-languages=${langs}

7. Luego, construye el gcc

     gmake 

8. Finalmente, Instale el gcc:

     gmake install

¡Eso es todo!

Aunque gcc.4.9.0 fue compilado, el paso se puede seguir para compilar otras versiones también.

Es posible que desee probar su gcc recién instalado para ver si funciona o no,así es como:

Cree un archivo simple hello.c como este

#include 

int
main (void)
{
  printf ("Hello, world!\n");
  return 0;
}

luego desde el terminal use

   /opt//opt/gcc-4.9.0/bin/gcc hello.c -o hello

You should see hello filed created in the same directory as hello.c

2
22.09.2017, 07:43
3 ответа

stdin и stdout— это всего лишь файловые дескрипторы 0 и 1 процесса и любое описание открытого файла , на которое они указывают, сами по себе являющиеся результатом, например, открытия файла системой open()вызов или создание канала с pipe()или open()в именованном канале, или сокет с connect()/ accept()/ socketpair()и т. д.

По крайней мере, большинство из них смогут читать и записывать любую последовательность байтов в виде потока. Для тех, которые обычно используются для взаимодействия -между процессами, таких как каналы и потоковые сокеты, границы сообщений, как правило, не сохраняются.

Например, в командной строке оболочки, например:

writer | reader

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

Если writerвыполняет write(1, "foo", 3); write(1, "bar", 3), то readerне сможет сказать, что пришло два сообщения, если только не произойдет его read()между двумя операциями записи writer.

Существуют некоторые типы файлов, такие как сокеты дейтаграмм (UDP, SCTP или домен unix по крайней мере )или SOCK_SEQPACKETв некоторых системах, которые сохраняют границы сообщений, но вам потребуется API, отличный от read()и write(), если вы хотите разрешить пустые сообщения, и читатель должен заранее знать максимально возможный размер этих сообщений и выделить такой большой буфер для его приема. Вам все равно придется использовать какую-либо форму кодирования, чтобы указать природу содержимого этих сообщений.

Пример:

$ strace -e write dd bs=2 count=3 if=/dev/zero status=none | strace -fe read cat
write(1, "\0\0", 2)                     = 2
write(1, "\0\0", 2)                     = 2
write(1, "\0\0", 2)                     = 2
read(0, "\0\0\0\0\0\0", 131072)         = 6
read(0, "", 131072)                     = 0

3 записи размера 2, 1 чтение размера 6, хотя в зависимости от времени вы можете увидеть 3 чтения размера 2 или одно чтение размера 4 и одно чтение размера 2. Это было с каналом или SOCK _Пара сокетов STREAM.

С SOCK _Пара сокетов SEQPACKET:

$ perl -MSocket -e '
   socketpair(my $rdr, my $wtr, AF_UNIX, SOCK_SEQPACKET, PF_UNSPEC);
   shutdown($rdr, 1); shutdown($wtr, 0);
   if (fork) {
     open STDIN, "<&", $rdr; close $wtr; close $rdr; sleep 1;
     exec qw(strace -e read cat)
   } else {
     open STDOUT, ">&", $wtr; close $rdr; close $wtr;
     exec qw(strace -e write dd count=3 bs=2 status=none if=/dev/zero)
   }'
write(1, "\0\0", 2)                     = 2
write(1, "\0\0", 2)                     = 2
write(1, "\0\0", 2)                     = 2
+++ exited with 0 +++
read(0, "\0\0", 131072)                 = 2
read(0, "\0\0", 131072)                 = 2
read(0, "\0\0", 131072)                 = 2
read(0, "", 131072)                     = 0
+++ exited with 0 +++

Это 3 чтения для этих 3 записей, даже несмотря на то, что мы задержали чтение на одну секунду, спустя много времени после завершения записи.

Итак, в конце концов, лучше всего так или иначе кодировать тип и длину. Компактная форма, которая позволяет читателю обрабатывать данные, как только они приходят (, но автор, чтобы знать длину сообщения заранее ), должен использовать TLV (тип, длину, значение )кодировка . Вам по-прежнему необходимо, чтобы автор и читатель договорились о длине и типе слов «тип» и «длина» (, например, 32-битное целое число с прямым порядком байтов )и о том, как интерпретировать значения типа.

Или вы можете использовать любой из множества существующих форматов сериализации, которые производят текст , который также более безопасен для обмена между системами с разным порядком байтов или каналами, которые не допускают байты NUL или делают какую-то строку транскодирование разделителя. Например, json, XML, perl Data::Dumper, php serialize(), вывод некоторых оболочек typeset -pв зависимости от используемого языка...

2
27.01.2020, 21:49

Вы не объясняете, что такое ваш стандартный вывод и куда он идет! (Например, стандартный вывод приложения CGI отправляется -косвенно -в какой-либо браузер ).

Философия Unix и конвейеры Unix требуют, чтобы stdin и stdout были обычным текстом, но это всего лишь соглашение . В некоторых случаях у вас могут быть другие соглашения (, например lprили lp, которые часто предпочитают PDF на стандартном вводе ).

Если вы программируете какую-либо программу, вы можете указать для нее какой-либо режим (, например. указывается некоторым программным аргументом )для вывода более структурированного текста, такого как JSON или XML или CSV или YAML . Обратите внимание, что jq может обрабатывать JSON.

Некоторые программы обнаруживают (, используя isatty и/или fstat ), когда их stdout(или их stdin)являются терминалом и действуют соответственно (возможно, используя ncurses , termios или escape-коды ANSI).

Многие текстовые форматы (, в частности XML ), имеют обычные начальные символы или заголовки, поэтому в некоторых случаях возможно их угадывание (, т.е. определение формата файла ). Посмотрите также MIME и libmagicфайл (1)).

I have a script that produces two different (unknown) strings and two different (unknown) numbers for each file it processes. Then there is another script that reads from STDIN to process each of the given strings, numbers. How can I format the output of the first script, so that the second can be made to identify each type correctly?

Если вы знаете (и документируете ), что неизвестные строки достаточно хороши, чтобы не содержать управляющих символов, таких как символы новой строки (, поэтому каждая из них представляет собой одну строку ), вы можете выбрать какой-то формат, например

FIRSTSTRING:первая строка

FIRSTNUMBER:первый номер

например

 FIRSTSTRING: foo bar is nice!
 FIRSTNUMBER: 42

затем напишите и используйте какой-нибудь простой awkскрипт (или, возможно, используйтеsed)для второго скрипта

Другими словами, принять решение и задокументировать простой специальный -формат; в вашем случае может быть проще в обращении, чем JSON. У вас могут быть свои собственные -специальные соглашения, если вы задокументируете их (, возможно, используя некоторые EBNF нотации ).

Многие инструменты уже готовы к этому; например, ps, ls, dfи ifconfigимеют специальные -специальные, но хорошо задокументированные выходные форматы и соглашения. И аналогично для proc (5). Следовательно, многие сценарии могут анализировать такие выходные данные.

Однако JSON был разработан, чтобы быть простым, гибким, масштабируемым, расширяемым,... И он способен представлять произвольные строки (даже с управляющими символами, большим количеством строк и т. д. ). Если для вас это важно, используйте его.

Можно заново изобрести и заново реализовать все утилиты Unix для вывода, например. JSON или XML (, но для этого требуется много работы ). Например, некоторые люди заново изобрели proc (5)и сделали модулем ядра, чтобы иметь псевдофайловую систему /xmlproc/вместо /proc/, которая выводила системные данные ядра в некоторая XML-форма. Но это не увенчалось успехом! Социальные соглашения имеют большое значение (, поэтому так важно задокументировать формат вывода, по крайней мере, в длинном комментарии ).

(Даже если вы используете JSON или XML, вам необходимо задокументировать, как вы их используете)

Кстати, многие существующие инструменты Unix могут добавлять тонкости в соглашения. Например, пробел, табуляция или символ возврата в пути к файлу возможны (см. путь _разрешение (7 )), но на (это может быть неодобрительно, поэтому я никогда этого не делаю ). Каталог $HOMEнекоторого пользователя теоретически может содержать символ возврата или двоеточие, но если вы это сделаете, большинство инструментов пострадает (, и вы, вероятно, сломаете passwd (5).. ). Пути к файлам, начинающиеся с тире, неудобны, как и очень длинные пути (, например. ваш $HOMEтеоретически может состоять из 3000 символов, но это было бы действительно неразумно ).

7
27.01.2020, 21:49

У вас есть два скрипта, один выдает две строки и два числа. Вам решать, как разобрать это во втором скрипте как две строки и два числа.

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

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

Не существует типов данных, которые можно применить к данным, кроме тех, которые вы создаете сами, выбирая конкретный «контракт» или «протокол» между вашими двумя сценариями или программами.

Некоторые стандартные инструменты Unix, такие как sortи cut, предполагают ввод данных в определенном формате, но их можно заставить изменить интерпретацию входных данных с помощью параметров командной строки.

Надуманный пример:

#!/bin/sh

echo 'first string'
echo 'second string'

echo '1.1'
echo '3.14'

Затем второй скрипт читает это:

#!/bin/sh

IFS= read -r string1
IFS= read -r string2
read number1 number2

Или с помощью JSON:

#!/bin/sh

echo '{ "string1": "hello", "string2": "world", "numbers": [1.1,3.14] }'

Второй сценарий:

#!/bin/sh

jq -r '"A number: \(.numbers[])"'
7
27.01.2020, 21:49

Теги

Похожие вопросы