Я использую Qt и bash поверх него, нужно выполнить что-то вроде:
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"
все отлично.
Я пытался что-то лайк
"cat file \\| grep string",
"cat file \| grep string"
но результат тот же. Если я копирую команду и запускаю ее в bash, то все в порядке.
QString::toAscii().data()
и другие преобразования также имеют плохой результат.
Проблема в том, что вы не можете запустить системную команду с QProcess, а только один процесс. Таким образом, обходной путь будет передавать вашу команду в качестве аргумента для bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
Быстрый и грязный хак был бы такой:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
Вы также можете избежать побега с помощью C ++ 11 R""
, но дело в том, что не используют bash
там, потому что это заставит его работать только с Bash. Он не будет работать на встроенном с busybox без bash, только ash или любой другой обычной оболочки рабочего стола.
/bin/sh
обычно это символическая ссылка на используемый интерпретатор оболочки, так что в конечном итоге это сработает.
НО!
Я думаю, что вы думаете о слишком низком уровне при использовании высокоуровневой среды C ++ / OOP, такой как Qt. Я бы не рекомендовал вызывать команды низкоуровневым способом при запуске из bash. Для этого случая есть специальный высокоуровневый удобный API.
На основе официальная документация, QProcess должен работать для команд pipe’d:
void QProcess :: setStandardOutputProcess (QProcess * destination)
Передает стандартный поток вывода этого процесса к стандартному вводу процесса назначения.
Другими словами, команда1 | Команда 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.
Проблема в том, что когда вы вызываете process-> start (cmd), все команды, следующие за вызовом cat, интерпретируются как аргументы cat, поэтому канал не выполняет то, что вы ожидаете. Если вы начинаете с вызова bash с параметром строки, вы должны получить то, что хотите: —
QString cmd = "bash -c \"cat file | grep string\"";
В качестве альтернативы, вы можете просто вызвать «cat file» и выполнить поиск по возвращенной QString при чтении вывода из QProcess
как насчет этого :
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);