首页 > 解决方案 > 在 C 中用颜色复制当前路径

问题描述

我正在使用 Linux Ubuntu,我想用着色复制当前的终止路径。本质上,我希望我的程序使用用户终端的颜色来打印\u@\h:\w$这篇文章换句话说,完全复制了(user)@(host):(pwd)$向下着色的路径。


我遇到的两个问题:

1)我正在尝试使用system("\u@\h:\w$ "),但无论我做什么,我都无法逃脱特殊字符。

2) 我找不到用户使用的颜色。

标签: cshell

解决方案


这里的问题很少。
解析PS1环境变量由 shell 完成。Shell(例如 bash)正在将 '\u' 字符串转换为 '(user)'。这不是系统调用。
系统调用执行一个文件名,因此system("\u@\h:\w$ ")您希望执行一个名为\u@\h:\w$. 我认为您的系统上没有这样的程序,这不是您的意图。您想打印当前记录的用户名,而不是执行名为“\u”的程序。您想执行名为whoami的程序,它将打印当前用户的用户名。
不知道你要什么颜色。unix shell 中的着色是使用ANSI 转义码完成的. 您只需 printf 一堆字符,您的终端就会为所有后续字符着色。
用 C 程序打印这个精确的输出比这更复杂,无论如何挑战等待着。以下程序将打印(user)@(host):(pwd)$. 部分(user)@为红色,部分(host):为黄色,部分(pwd)$为洋红色。我正在使用popen posix 调用来执行一个进程并获取它的输出。

#define _GNU_SOURCE
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_RESET   "\x1b[0m"

void exec_and_grab_output(const char cmd[], char *outbuf, size_t outbuflen) {
    size_t outbufpos = 0;
    FILE *fp;
    char tmpbuf[100];
    /* Open the command for reading. */  
    fp = popen(cmd, "r");
    assert(fp != NULL);
    /* Read the output a line at a time - output it. */
    while (fgets(tmpbuf, sizeof(tmpbuf)-1, fp) != NULL) {
        assert(outbufpos <= outbuflen);
        const size_t tmpbufpos = strlen(tmpbuf);
        memcpy(&outbuf[outbufpos], tmpbuf, tmpbufpos);
        outbufpos += tmpbufpos;
    }
    /* close */
    pclose(fp);
}

int main()
{
    char outbuf[2048];

    exec_and_grab_output("whoami", outbuf, sizeof(outbuf));
    printf(ANSI_COLOR_RED);
    assert(strlen(outbuf) > 2);
    outbuf[strlen(outbuf)-2] = '\0'; // remove newline from output
    printf("%s@", outbuf); // this will be red

    exec_and_grab_output("hostname", outbuf, sizeof(outbuf));
    printf(ANSI_COLOR_YELLOW);
    assert(strlen(outbuf) > 2);
    outbuf[strlen(outbuf)-2] = '\0'; // remove newline from output
    printf("%s:", outbuf); // this will be yellow

    exec_and_grab_output("pwd", outbuf, sizeof(outbuf));
    printf(ANSI_COLOR_MAGENTA);
    assert(strlen(outbuf) > 2);
    outbuf[strlen(outbuf)-2] = '\0'; // remove newline from output
    printf("%s$", outbuf); // this will be in magenta

    printf(ANSI_COLOR_RESET);

    return 0;
}

如果你想在 shell 中着色 PS1 变量的输出(不是 C,C 是一种编程语言,shell 是一个程序),你可以在你的 bash 终端中输入:

export PS1="\033[31m\u@\033[33m\h:\033[36m\w$\033[0m"

该部分与上面 C 程序中\033[31m的部分 1:1 对应。"\x1b[31m"Bash 会将\033[31m字符打印到终端(当打印 PS1 时),然后终端会将所有后续字符着色为红色。Bash 将扩展\u为当前用户的名称。等等。


推荐阅读