web-dev-qa-db-ja.com

QProcessを使用した配管(またはコマンドチェーン)

私は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()

そして他の変換も悪い結果をもたらします。

16

問題は、QProcessでシステムコマンドを実行できず、単一のプロセスしか実行できないことです。したがって、回避策は、コマンドを引数としてbashに渡すことです。

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

迅速で汚いハックはこれです:

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

C++ 11の_R""_を使用してそこにエスケープすることを回避することもできますが、重要なのは、bashでのみ機能するため、そこでbashを使用しないことです。 bash、単にash、またはその他の一般的なデスクトップシェルなしでbusyboxが埋め込まれた場合は機能しません。

_/bin/sh_は通常、使用されるシェルインタープリターへのシンボリックリンクであるため、最終的には機能します。

しかし!

Qtなどの高レベルのC++/OOPフレームワークを使用する場合、少し低レベルを考えていると思います。 bashからコマンドを実行するときに、低レベルの方法でコマンドを呼び出すことはお勧めしません。このユースケースには、専用の高レベルの便利なAPIがいくつかあります。

公式ドキュメント に基づいて、QProcessはパイプされたコマンドに対して機能することになっています:

void QProcess :: setStandardOutputProcess(QProcess * destination)

このプロセスの標準出力ストリームを宛先プロセスの標準入力にパイプします。

つまり、command1 | command2シェルコマンドコマンドは、次の方法で実行できます。

_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はQt5で非推奨になりました。

24
lpapp

問題は、process-> start(cmd)を呼び出すと、catの呼び出しに続くコマンドがすべてcatへの引数として解釈されるため、パイプが期待どおりに動作しないことです。文字列のパラメータを使用してbashを呼び出すことから始めると、必要なものが得られるはずです。

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

または、「cat file」を呼び出して、QProcessからの出力を読み取るときに、返されたQStringを検索することもできます。

3
TheDarkKnight

これはどう :

QString program = "program";
QStringList arguments;

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