Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在QProcess输出中保留ANSI转义序列 我正在创建一个程序,在Qt中运行QualPosits,使用Ubuntu 16.04 Qt5.5.1,其中启用了C++ 11。我将进程输出流定向到QTextEdit_Linux_Bash_Qt_Ansi_Qprocess - Fatal编程技术网

Linux 在QProcess输出中保留ANSI转义序列 我正在创建一个程序,在Qt中运行QualPosits,使用Ubuntu 16.04 Qt5.5.1,其中启用了C++ 11。我将进程输出流定向到QTextEdit

Linux 在QProcess输出中保留ANSI转义序列 我正在创建一个程序,在Qt中运行QualPosits,使用Ubuntu 16.04 Qt5.5.1,其中启用了C++ 11。我将进程输出流定向到QTextEdit,linux,bash,qt,ansi,qprocess,Linux,Bash,Qt,Ansi,Qprocess,我想将此输出着色,以使用本地终端通过使用嵌入的ANSI转义颜色序列解释的相同颜色。但是,我无法解析转义序列,因为QProcess输出中似乎缺少它们。我原本以为QString正在剥离它们,但经过一些测试后,我认为情况并非如此 我发现,如果我能在QProcess输出中保留转义序列,就可以为我指明ANSI转义颜色解释方向 下面是我在Qt代码中所做的一个示例项目 源文件 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QSt

我想将此输出着色,以使用本地终端通过使用嵌入的ANSI转义颜色序列解释的相同颜色。但是,我无法解析转义序列,因为QProcess输出中似乎缺少它们。我原本以为QString正在剥离它们,但经过一些测试后,我认为情况并非如此

我发现,如果我能在QProcess输出中保留转义序列,就可以为我指明ANSI转义颜色解释方向

下面是我在Qt代码中所做的一个示例项目

源文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <QProcess>
#include <QStringList>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList input = {"gcc will_not_build.c"};
    QProcess * proc = new QProcess();

    proc->setReadChannel(QProcess::StandardOutput);
    proc->setProcessChannelMode(QProcess::MergedChannels);
    proc->setWorkingDirectory("/path/to/test/c/file/");

    //Start bash
    proc->start("bash");
    proc->waitForStarted();

    // Write as many commands to this process as needed
    foreach(QString str, input){
        proc->write(str.toUtf8() + "\n");
        proc->waitForBytesWritten(-1);
    }

    // Let bash close gracefully
    proc->write("exit $?\n");
    proc->waitForBytesWritten(-1);

    proc->closeWriteChannel();
    proc->waitForFinished();
    proc->waitForReadyRead();

    QByteArray read_data = proc->readAll();

    // The use of tr(read_data) also works here.
    QString output = tr(read_data);//QString::fromStdString (read_data.toStdString ());

    proc->closeReadChannel(QProcess::StandardOutput);

    proc->close();
    delete proc;

    // Add the output to the text box
    ui->textEdit->append (output);
}

MainWindow::~MainWindow()
{
    delete ui;
}
int main(){
    // Intentionally will not build
    I will not build :)
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <QProcess>
#include <QStringList>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList input = {"unbuffer gcc will_not_build.c"};
    QProcess * proc = new QProcess();

    proc->setReadChannel(QProcess::StandardOutput);
    proc->setProcessChannelMode(QProcess::MergedChannels);
    proc->setWorkingDirectory("/path/to/test/c/file/");

    //Start bash
    proc->start("bash");
    proc->waitForStarted();

    // Write as many commands to this process as needed
    foreach(QString str, input){
        proc->write(str.toUtf8() + "\n");
        proc->waitForBytesWritten(-1);
    }

    // Let bash close gracefully
    proc->write("exit $?\n");
    proc->waitForBytesWritten(-1);

    proc->closeWriteChannel();
    proc->waitForFinished();
    proc->waitForReadyRead();

    QByteArray read_data = proc->readAll();

    // The use of tr(read_data) also works here.
    QString output = tr(read_data);//QString::fromStdString (read_data.toStdString ());

    proc->closeReadChannel(QProcess::StandardOutput);

    proc->close();
    delete proc;

    // Strip default character set escape sequences, since those seem to be left
    // See https://stackoverflow.com/questions/36279015/what-does-x1bb-do
    output.remove("\x1b(B", Qt::CaseInsensitive);

    // Since it is just one single text stream define here instead of globally
    Utils::AnsiEscapeCodeHandler ansi_handler;

    FormattedTextList result = ansi_handler.parseText (Utils::FormattedText(output, ui->textEdit->currentCharFormat ()));

    // Loop through the text/format results
    foreach(Utils::FormattedText ft, result){
        ui->textEdit->setCurrentCharFormat (ft.format);
        ui->textEdit->insertPlainText (ft.text);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
我的输出如下所示:

QProcess gcc输出

本机Linux终端的输出如下所示:

带颜色的Linux终端gcc输出

有人知道我如何在QProcess输出中保留ANSI转义颜色序列,以便模拟Linux终端颜色吗


作为旁注,我在Qt-Creator源代码中进行了深入研究,有一个类可以将ANSI转义颜色转换为富文本颜色,因此我知道有人已经走上了这条路。同样,在构建项目时,由于某种原因,Qt Creator不会在自己的终端中为构建输出着色。

QProcess
不会干扰过程输出,只是,
gcc
——就像许多其他发出彩色输出的程序一样——默认情况下,只有在检测到正在TTY设备上写入时才会发出彩色转义序列


如果要禁用此启发式并要求始终生成彩色输出,则必须将
-fddiagnostics color=always
选项添加到编译器命令行

QProcess
不会干扰进程输出,只是
gcc
——就像许多其他发出彩色输出的程序一样——默认情况下,只有在检测到正在TTY设备上写入时才会发出彩色转义序列


如果要禁用此启发式并要求始终生成彩色输出,则必须将
-fddiagnostics color=always
选项添加到编译器命令行

多亏了对我问题的深刻回答,我才找到了解决问题的办法。我将分享

QProcess没有故障,QString也没有故障。问题在于程序执行的环境。由于这些程序(gcc等)的输出未连接到TTY设备,因此所有ANSI转义序列都被剥离。不过,还是有办法的

只需在命令前面加上
unbuffer

因为我的使用实际上是创建一个QtCreator插件,所以我已经链接了QtCreator的大部分源代码。碰巧已经存在一个名为AnsiEscapeCodeHandler的方便类,用于将ANSI转义序列转换为相应的ANSI转义序列字符串

为了说明我是如何使用这个类的,但现在在我的示例中,我将从可下载的Qt Creator源代码中将
ansiescapecodehandler.h
ansiescapecodehandler.cpp
复制到我的测试项目中。我不得不从
AnsiEscapeCodeHandler
源文件中删除几行代码,以便在Qt Creator源代码其余部分的上下文之外进行编译,但仅此而已

新的源文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <QProcess>
#include <QStringList>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList input = {"gcc will_not_build.c"};
    QProcess * proc = new QProcess();

    proc->setReadChannel(QProcess::StandardOutput);
    proc->setProcessChannelMode(QProcess::MergedChannels);
    proc->setWorkingDirectory("/path/to/test/c/file/");

    //Start bash
    proc->start("bash");
    proc->waitForStarted();

    // Write as many commands to this process as needed
    foreach(QString str, input){
        proc->write(str.toUtf8() + "\n");
        proc->waitForBytesWritten(-1);
    }

    // Let bash close gracefully
    proc->write("exit $?\n");
    proc->waitForBytesWritten(-1);

    proc->closeWriteChannel();
    proc->waitForFinished();
    proc->waitForReadyRead();

    QByteArray read_data = proc->readAll();

    // The use of tr(read_data) also works here.
    QString output = tr(read_data);//QString::fromStdString (read_data.toStdString ());

    proc->closeReadChannel(QProcess::StandardOutput);

    proc->close();
    delete proc;

    // Add the output to the text box
    ui->textEdit->append (output);
}

MainWindow::~MainWindow()
{
    delete ui;
}
int main(){
    // Intentionally will not build
    I will not build :)
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <QProcess>
#include <QStringList>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList input = {"unbuffer gcc will_not_build.c"};
    QProcess * proc = new QProcess();

    proc->setReadChannel(QProcess::StandardOutput);
    proc->setProcessChannelMode(QProcess::MergedChannels);
    proc->setWorkingDirectory("/path/to/test/c/file/");

    //Start bash
    proc->start("bash");
    proc->waitForStarted();

    // Write as many commands to this process as needed
    foreach(QString str, input){
        proc->write(str.toUtf8() + "\n");
        proc->waitForBytesWritten(-1);
    }

    // Let bash close gracefully
    proc->write("exit $?\n");
    proc->waitForBytesWritten(-1);

    proc->closeWriteChannel();
    proc->waitForFinished();
    proc->waitForReadyRead();

    QByteArray read_data = proc->readAll();

    // The use of tr(read_data) also works here.
    QString output = tr(read_data);//QString::fromStdString (read_data.toStdString ());

    proc->closeReadChannel(QProcess::StandardOutput);

    proc->close();
    delete proc;

    // Strip default character set escape sequences, since those seem to be left
    // See https://stackoverflow.com/questions/36279015/what-does-x1bb-do
    output.remove("\x1b(B", Qt::CaseInsensitive);

    // Since it is just one single text stream define here instead of globally
    Utils::AnsiEscapeCodeHandler ansi_handler;

    FormattedTextList result = ansi_handler.parseText (Utils::FormattedText(output, ui->textEdit->currentCharFormat ()));

    // Loop through the text/format results
    foreach(Utils::FormattedText ft, result){
        ui->textEdit->setCurrentCharFormat (ft.format);
        ui->textEdit->insertPlainText (ft.text);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括
#包括
#包括
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
QStringList输入={“unbuffer gcc will_not_build.c”};
QProcess*proc=新的QProcess();
proc->setReadChannel(QProcess::StandardOutput);
proc->setProcessChannelMode(QProcess::MergedChannels);
proc->setWorkingDirectory(“/path/to/test/c/file/”;
//开始狂欢
proc->start(“bash”);
proc->waitForStarted();
//根据需要向该进程写入尽可能多的命令
foreach(QString str,输入){
proc->write(str.toUtf8()+“\n”);
proc->WaitForBytesWrited(-1);
}
//让bash优雅地关闭
过程->写入(“退出$?\n”);
proc->WaitForBytesWrited(-1);
proc->closeWriteChannel();
proc->waitForFinished();
proc->waitForReadyRead();
QByteArray read_data=proc->readAll();
//tr(read_data)的使用在这里也起作用。
QString output=tr(read_data);//QString::fromStdString(read_data.toStdString());
proc->closeReadChannel(QProcess::StandardOutput);
proc->close();
删除proc;
//剥离默认字符集转义序列,因为这些转义序列似乎是左转义序列
//看https://stackoverflow.com/questions/36279015/what-does-x1bb-do
output.remove(“\x1b(B”,Qt::不区分大小写);
//因为它只是一个文本流,所以在这里定义而不是全局定义
Utils::AnsiEscapeCodeHandler ansi_handler;
FormattedTextList结果=ansi_handler.parseText(Utils::FormattedText(输出,ui->textEdit->currentCharFormat());
//循环浏览文本/格式结果
foreach(Utils::FormattedText ft,结果){
用户界面->文本编辑->设置当前字符格式(ft.format);
用户界面->文本编辑->插入明文(ft.text);
}
}
MainWindow::~MainWindow()
{
删除用户界面;
}
新的头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H 
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

// This exists in the qtcreator-src code and handles ansi escape code color parsing
#include "ansiescapecodehandler.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    typedef QList<Utils::FormattedText> FormattedTextList;
};

#endif // MAINWINDOW_H
\ifndef主窗口
#定义主窗口
#包括
//这存在于qtcreator src代码中,并处理ansi转义代码颜色解析
#包括“ansiescapecodehandler.h”
名称空间用户界面{
类主窗口;
}
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=0);
~main窗口();
私人:
Ui::MainWindow*Ui;
typedef QList FormattedTextList;
};
#endif//main窗口
新的彩色输出。。。
多亏了对我问题的深刻回答,我才能够