[英]Piping (or command chaining) with QProcess
I'm using Qt and bash over it, need to execute something like:我正在使用 Qt 并对其进行 bash,需要执行如下操作:
bash: cat file | grep string
in Qt:在 Qt 中:
QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
The problem is in pipe ("|"), and process returs nothing.问题出在管道(“|”)中,并且进程没有返回任何内容。 If there is no ("|"), like
如果没有(“|”),比如
"cat file"
everything is ok.一切正常。 I tried smth.
我试过了。 like
像
"cat file \\| grep string",
"cat file \| grep string"
but result is the same.但结果是一样的。 If I copy the command and run it in bash everything is ok.
如果我复制命令并在 bash 中运行它,一切正常。
QString::toAscii().data()
and other transforms also have bad result.和其他转换也有不好的结果。
The problem is you cannot run a system command with QProcess, but only a single process.问题是您不能使用 QProcess 运行系统命令,而只能运行单个进程。 So the workaround will be to pass your command as an argument to bash:
因此,解决方法是将您的命令作为参数传递给 bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
The quick and dirty hack would be this:快速而肮脏的黑客将是这样的:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
You could also avoid the escaping in there with C++11's R""
, but the point is that do not use bash
in there because that will make it only work with bash.您也可以避免使用 C++11 的
R""
进行转义,但重点是不要在其中使用bash
,因为这将使其仅适用于 bash。 It will not work on embedded with busybox without bash, just ash, or any other common desktop shell.它不能在没有 bash、只有 ash 或任何其他常见桌面 shell 的情况下嵌入 busybox。
/bin/sh
is usually a symlink to the shell interpreter used, so that will eventually work. /bin/sh
通常是所使用的 shell 解释器的符号链接,因此最终会起作用。
BUT!但是!
I think you are thinking a bit too low-level when using a high-level C++/OOP framework such as Qt.我认为在使用高级 C++/OOP 框架(如 Qt)时,您的想法有点太低级了。 I would not recommend to invoke the commands in the low-level way when you run it from bash.
当您从 bash 运行它时,我不建议以低级方式调用命令。 There is some dedicated high-level convenience API for this use case.
此用例有一些专用的高级便利 API。
Based on the official documentation , QProcess is supposed to work for pipe'd commands:根据官方文档,QProcess 应该适用于管道命令:
void QProcess::setStandardOutputProcess(QProcess * destination)
void QProcess::setStandardOutputProcess(QProcess * destination)
Pipes the standard output stream of this process to the destination process' standard input.
将此进程的标准输出流通过管道传输到目标进程的标准输入。
In other words, the command1 |换句话说,command1 | command2 shell command command can be achieved in the following way:
command2 shell command 命令可以通过以下方式实现:
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;
This is not the main point, but a useful suggestion: do not use QString::toAscii()
.这不是重点,而是一个有用的建议:不要使用
QString::toAscii()
。 That API has been deprecated in Qt 5.该 API 在 Qt 5 中已被弃用。
The problem is that when you call process->start(cmd), the commands following the the call to cat are all interpreted as arguments to cat, so the pipe is not doing what you're expecting.问题是当你调用 process->start(cmd) 时,调用 cat 之后的命令都被解释为 cat 的参数,所以管道没有做你期望的。 If you start with a call to bash with a parameter of a string, you should get what you want: -
如果您从使用字符串参数调用 bash 开始,您应该得到您想要的:-
QString cmd = "bash -c \"cat file | grep string\"";
Alternatively, you could just call "cat file" and do the search on the returned QString when you read the output from the QProcess或者,当您从 QProcess 读取输出时,您可以调用“cat file”并在返回的 QString 上进行搜索
how about this :这个怎么样:
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);
If Google brought you here and you are using PyQt5 or PySide2如果谷歌把你带到这里并且你使用的是 PyQt5 或 PySide2
process1 = QProcess()
process2 = QProcess()
process1.setStandardOutputProcess(process2)
process1.start(cat, [file])
process2.start(grep, [string])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.