使用QProcess进行管道(或命令链接)

时间:2014-01-03 10:51:01

标签: c++ qt shell qprocess chain

我正在使用Qt并对其进行打击,需要执行以下操作:

bash: cat file | grep string
在Qt中

QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();

问题在于管道(“|”),并且进程没有任何回复。如果没有(“|”),比如

"cat file" 
一切都好。 我试过smth。喜欢

"cat file \\| grep string", 
"cat file \| grep string" 

但结果是一样的。如果我复制命令并在bash中运行它一切正常。

QString::toAscii().data()

和其他变换也有不好的结果。

5 个答案:

答案 0 :(得分:24)

快速而肮脏的黑客就是这样:

QString cmd = "/bin/sh -c \"cat file | grep string\"";

你也可以避免使用C ++ 11的R""进行转义,但重点是不要在那里使用bash,因为这样只能使用bash。如果没有bash,只有ash或任何其他常见的桌面shell,它将无法在busybox中嵌入。

/bin/sh通常是所使用的shell解释器的符号链接,因此最终会有效。

<强> BUT!

我认为在使用Qt这样的高级C ++ / OOP框架时,你的想法太低了。当你从bash运行它时,我不建议以低级方式调用命令。这个用例有一些专用的高级便利API。

基于official documentation,QProcess应该适用于管道命令:

  

void QProcess :: setStandardOutputProcess(QProcess * destination)

     

将此流程的标准输出流管道传输到目标流程的标准输入。

换句话说,command1 | command2 shell命令命令可以通过以下方式实现:

QProcess process1;
QProcess process2;

process1.setStandardOutputProcess(&process2);

process1.start("cat file");
process2.start("grep string");
process2.setProcessChannelMode(QProcess::ForwardedChannels);

// Wait for it to start
if(!process1.waitForStarted())
    return 0;

bool retval = false;
QByteArray buffer;
while ((retval = process2.waitForFinished()));
    buffer.append(process2.readAll());

if (!retval) {
    qDebug() << "Process 2 error:" << process2.errorString();
    return 1;
}

qDebug() << "Buffer data" << buffer;

这不是重点,而是一个有用的建议:不要使用QString::toAscii()。该API已在Qt 5中弃用。

答案 1 :(得分:23)

问题是您不能使用QProcess运行系统命令,而只能运行单个进程。因此,解决方法是将您的命令作为参数传递给bash:

process.start("bash", QStringList() << "-c" << "cat file | grep string");

答案 2 :(得分:3)

问题在于,当你调用process-&gt; start(cmd)时,对cat调用之后的命令都被解释为cat的参数,因此管道没有按照你的期望进行操作。如果你开始使用字符串参数调用bash,你应该得到你想要的: -

QString cmd = "bash -c \"cat file | grep string\"";

或者,你可以调用“cat file”并在读取QProcess的输出时对返回的QString进行搜索

答案 3 :(得分:0)

怎么样:

QString program = "program";
QStringList arguments;

download = new QProcess(this);
download->start(program, arguments);

答案 4 :(得分:0)

如果 Google 将您带到这里并且您使用的是 PyQt5 或 PySide2

        process1 = QProcess()
        process2 = QProcess()
        process1.setStandardOutputProcess(process2)
        process1.start(cat, [file])
        process2.start(grep, [string])