为什么捕获到 Bash 变量时 libncurses ui 不显示?
Why does libncurses ui not display when capturing to Bash variable?
我写了一个基于 libcurses 的 ascii ui,它在程序退出时将文本写入标准输出。
如果我一个人执行程序,像这样...
> ./test
...ui 显示。
但是,如果我尝试将程序输出捕获到 Bash 变量,就像这样...
> foo=$(./test)
...ui 不显示,但是 Bash 变量捕获预期的输出。
有谁知道为什么会这样?有没有办法让 ui 在尝试将其标准输出捕获到 Bash 变量时显示?
代码
#include <iostream>
#include <curses.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
WINDOW* pWindow = initscr();
keypad(pWindow, TRUE);
curs_set(0);
nodelay(pWindow, FALSE);
mvwprintw(pWindow, 5, 5, "hello, world!");
mvwprintw(pWindow, 6, 5, "hello, fold!");
mvwprintw(pWindow, 7, 5, "hello, toad!");
for (int i = 0; i < 5; ++i)
{
mvwprintw(pWindow, 5 + i, 1, "==>");
refresh();
usleep(500000);
mvwprintw(pWindow, 5 + i, 1, " ");
refresh();
}
endwin();
std::cout << "bar" << std::endl;
}
仅仅是因为重定向标准输出(>
、a=$(…)
)只是重定向标准输出——另一方面,ncurses 直接与终端对话并显示字符,这些字符从来都不是一部分标准输出。
短:它没有捕获输出,因为有 none。相反,ncurses 程序直接与底层终端对话。
Is there a way to get the ui to show up when trying to capture its stdout to a Bash variable?
我不推荐这样做。因为您混合使用了非交互式用法(获取标准输出)和交互式用法,所以最终效果不佳,但是:
您可以结束您的 ncurses 会话并像任何其他 C 程序员一样使用 printf
。然后你实际上会产生标准输出。
我更愿意向我的程序添加一个选项,该选项接受一个我写入输出的文件。然后 bash 脚本可以在我的程序具有 运行.
之后打开该文件
当您使用 initscr
, it will use the standard output for display. (You could use newterm
初始化 curses 以指定另一个输出时)。因此,当您重定向程序的输出时,您将看不到用户界面。
调整您的示例,
#!/bin/bash
g++ -o test foo.c $(ncursesw6-config --cflags --libs)
foo=$(./test)
set >foo.log
并查看 bash 放入 $foo
的内容,我看到了用户界面中写入的预期控制字符,例如
foo=$'\E[?1049h\E[1;40r\E(B\E[m\E[4l\E[?7h\E[?1h\E=\E[?25l\E[H\E[2J\E[6d ==> hello, world!\n\E[6Ghello, fold!\n\E[6Ghello, toad!\E[6;5H\r \r\n ==>\r \r\n ==>\r \r\n ==>\r\E[J \r\n ==>\r\E[J \E[40;1H\E[?12l\E[?25h\E[?1049l\r\E[?1l\E>bar'
我写了一个基于 libcurses 的 ascii ui,它在程序退出时将文本写入标准输出。
如果我一个人执行程序,像这样...
> ./test
...ui 显示。
但是,如果我尝试将程序输出捕获到 Bash 变量,就像这样...
> foo=$(./test)
...ui 不显示,但是 Bash 变量捕获预期的输出。
有谁知道为什么会这样?有没有办法让 ui 在尝试将其标准输出捕获到 Bash 变量时显示?
代码
#include <iostream>
#include <curses.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
WINDOW* pWindow = initscr();
keypad(pWindow, TRUE);
curs_set(0);
nodelay(pWindow, FALSE);
mvwprintw(pWindow, 5, 5, "hello, world!");
mvwprintw(pWindow, 6, 5, "hello, fold!");
mvwprintw(pWindow, 7, 5, "hello, toad!");
for (int i = 0; i < 5; ++i)
{
mvwprintw(pWindow, 5 + i, 1, "==>");
refresh();
usleep(500000);
mvwprintw(pWindow, 5 + i, 1, " ");
refresh();
}
endwin();
std::cout << "bar" << std::endl;
}
仅仅是因为重定向标准输出(>
、a=$(…)
)只是重定向标准输出——另一方面,ncurses 直接与终端对话并显示字符,这些字符从来都不是一部分标准输出。
短:它没有捕获输出,因为有 none。相反,ncurses 程序直接与底层终端对话。
Is there a way to get the ui to show up when trying to capture its stdout to a Bash variable?
我不推荐这样做。因为您混合使用了非交互式用法(获取标准输出)和交互式用法,所以最终效果不佳,但是:
您可以结束您的 ncurses 会话并像任何其他 C 程序员一样使用 printf
。然后你实际上会产生标准输出。
我更愿意向我的程序添加一个选项,该选项接受一个我写入输出的文件。然后 bash 脚本可以在我的程序具有 运行.
之后打开该文件当您使用 initscr
, it will use the standard output for display. (You could use newterm
初始化 curses 以指定另一个输出时)。因此,当您重定向程序的输出时,您将看不到用户界面。
调整您的示例,
#!/bin/bash
g++ -o test foo.c $(ncursesw6-config --cflags --libs)
foo=$(./test)
set >foo.log
并查看 bash 放入 $foo
的内容,我看到了用户界面中写入的预期控制字符,例如
foo=$'\E[?1049h\E[1;40r\E(B\E[m\E[4l\E[?7h\E[?1h\E=\E[?25l\E[H\E[2J\E[6d ==> hello, world!\n\E[6Ghello, fold!\n\E[6Ghello, toad!\E[6;5H\r \r\n ==>\r \r\n ==>\r \r\n ==>\r\E[J \r\n ==>\r\E[J \E[40;1H\E[?12l\E[?25h\E[?1049l\r\E[?1l\E>bar'