You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用execlp调用cut命令出现额外空行问题排查

问题原因及解决办法

额外空行的根源

你给cut传的参数错了。在child1里,你写的char *d="-d " "";会拼成"-d "(也就是-d后面带个空格),然后作为单个参数传给cut。但cut的-d选项要求选项和分隔符是两个分开的参数——正确姿势是把"-d"当一个参数,空格" "当另一个参数。

这种错误的参数传递会让cut解析混乱,输出就会多出来空行,和你在终端直接执行的效果不一样。

子进程卡着不退出的原因

父进程没关管道的两端!子进程1退出后,管道的写端还被父进程握着,子进程2的read就会一直等数据,直到所有写端都关闭才会返回0、结束循环。这就是为啥你的程序要等超时才能结束。

改好后的代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>

void wait_child() {
    int terminated, status;
    terminated=wait(&status);
    if (WIFEXITED(status)) {
        printf("Child termination ok\n");
    }else if (WIFSIGNALED(status)) {
        printf("Child termination not ok\n");
    }
}

void child1(int ppwrite, char* file) {
    char *f="-f2"; // 提取每行第二个字段
    dup2(ppwrite,1); // 把stdout转到管道写端
    close(ppwrite);
    // 修正cut参数:-d和空格分开传
    execlp("cut","cut", "-d", " ", f, file, (char*)0);
    perror("exec error");
}

void child2(int ppread) { 
    int nread,nlines;
    char buffer;
    nlines=0;
    printf("Line 1: ");
    while ((nread=read(ppread, &buffer, sizeof(buffer)))>0) {
        if (buffer=='\n') {
            nlines++;
            printf("\n");
            // 看看后面还有没有数据,有再打印下一行的提示
            char next;
            if (read(ppread, &next, 1) == 1) {
                lseek(ppread, -1, SEEK_CUR);
                printf("Line %d: ", nlines+1);
            }
        } else {
            printf("%c", buffer);
        }
    }
    close(ppread);
    printf("\n");
}

void handler(int signum) {
    if (signum==SIGALRM) {
        printf("Timeout\n");
        exit(EXIT_SUCCESS);
    }
}

int main(int argc, char* argv[]) {
    
    int pid1,pid2;
    int pp[2];
    
    if (pipe(pp)<0) {
        printf("Errore creazione pipe\n");
        exit(EXIT_FAILURE);
    }
    
    signal(SIGALRM, handler);
    alarm(5);
    
    pid1=fork();
    if (pid1<0) {
        printf("P1 could not be created\n");
        exit(EXIT_FAILURE);
    } else if (pid1==0) {
        close(pp[0]);
        child1(pp[1], "myfile.txt");
    } else {
        pid2=fork();
        if (pid2<0) {
            printf("P2 could not be created\n");
            exit(EXIT_FAILURE);
        } else if (pid2==0) {
            close(pp[1]);
            child2(pp[0]);
        } else {
            // 父进程必须关管道两端,不然子进程2会一直等
            close(pp[0]);
            close(pp[1]);
            for (int i=0; i<2; i++) {
                wait_child();
            }
        }
        
    }
    
}

核心改动点

  • cut参数修复:把原来的"-d "拆成"-d"和" "两个参数,让cut正确识别空格分隔符,解决额外空行问题。
  • 父进程关闭管道:主进程里fork完两个子进程后,立刻关闭管道的读写端,这样子进程1退出后,管道写端完全关闭,子进程2的read会返回0,正常结束循环。
  • 输出优化:读取到换行符时,先检查管道里还有没有后续数据,只有有数据才打印下一行的Line X:提示,避免最后多出一行空的提示。

内容的提问来源于stack exchange,提问作者Chiara Busca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:17:35