Использование каналов для перенаправления вывода из seq на ввод awk - PullRequest
0 голосов
/ 22 января 2020

В дочернем процессе я вызываю seq с 1 в качестве первого аргумента и первым аргументом командной строки в качестве второго аргумента. Затем я продолжаю использовать стандартный вывод seq в качестве ввода для второй команды awk. Эта команда получает второй аргумент командной строки в качестве аргумента. Проверка ошибок не относится к этой задаче, поэтому, пожалуйста, сконцентрируйтесь на функциональности.

В конце вывод awk должен быть напечатан на стандартный вывод.

Он должен имитировать что-то вроде: seq 1 10 | awk {printf}

Это то, как далеко я прошел, но я не получаю вывод:

#define READ 0
#define WRITE 1

int main(int argc, char *argv[]) {

int fd1[2];

if (pipe(fd1)==-1){ 
    fprintf(stderr, "Pipe Failed"); 
    return -1; 
}

int pidSeq = fork();
if(pidSeq == 0){
    close(fd1[READ]);
    dup2(fd1[WRITE], 1);
    close(fd1[WRITE]);
    execl("seq", "seq", "1", argv[1], NULL);
}
else if(pidSeq > 0){
    close(fd1[WRITE]);
    dup2(fd1[READ], 0);
    close(fd1[READ]);
    execl("awk", "awk", argv[2], NULL);
}

return 0;
}

1 Ответ

0 голосов
/ 22 января 2020

Используйте execlp() вместо execl().

Как написано, это будет работать, только если текущий каталог содержит и seq и awk.

Обратите внимание, что если вы сообщил об ошибке, если функции execl() вернутся (и они вернутся только при ошибке; они не вернутся при успешном выполнении), тогда вы бы знали, что происходило неправильно, без необходимости спрашивать.

Вот исправлена ​​версия вашего кода. Он использует некоторый код, который доступен в моем репозитории SOQ (Вопросы о переполнении стека) на GitHub в виде файлов stderr.c и stderr.h в подкаталоге src / libsoq . Это упрощает отчеты об ошибках.

#include <stdio.h>
#include <unistd.h>
#include "stderr.h"

#define READ 0
#define WRITE 1

int main(int argc, char *argv[])
{
    err_setarg0(argv[0]);
    if (argc != 3)
        err_usage("max 'awk script'");

    int fd1[2];
    if (pipe(fd1) == -1)
        err_syserr("failed to create a pipe: ");

    int pidSeq = fork();
    if (pidSeq == 0)
    {
        close(fd1[READ]);
        dup2(fd1[WRITE], 1);
        close(fd1[WRITE]);
        execlp("seq", "seq", "1", argv[1], NULL);
        err_syserr("failed to exec 'seq': ");
    }
    else if (pidSeq > 0)
    {
        close(fd1[WRITE]);
        dup2(fd1[READ], 0);
        close(fd1[READ]);
        execlp("awk", "awk", argv[2], NULL);
        err_syserr("failed to exec 'awk': ");
    }
    else
        err_syserr("failed to fork(): ");

    return 0;
}

Он был скомпилирован из seq-awk59.c в seq-awk59, а затем запущен как:

$ seq-awk59 15 '{sum += $1}END{print sum}'
120
$

Сначала я использовал версию с execl() execlp(). Вывод, который я получил, был:

$ seq-awk59 15 '{sum += $1}END{print sum}'
seq-awk59: failed to exec 'awk': error (2) No such file or directory
seq-awk59: failed to exec 'seq': error (2) No such file or directory
$

И неправильное использование программы генерирует сообщение об использовании:

$ seq-awk59 a b c
Usage: seq-awk59 max 'awk script'
$
...