为啥 QProcess 将我的参数中的“=”转换为空格

Posted

技术标签:

【中文标题】为啥 QProcess 将我的参数中的“=”转换为空格【英文标题】:Why is QProcess converting the '=' in my arguments to spaces为什么 QProcess 将我的参数中的“=”转换为空格 【发布时间】:2010-06-11 20:50:19 【问题描述】:

我在 Windows 上运行 Qt 程序时遇到了一个奇怪的错误。该程序使用 QProcess 生成具有两个参数的子进程。传递给 QProcess::start() 方法的程序和参数的格式为:

"batchfile.bat" "--option1=some_value" "--option2=some_other_value\with_a\path"

由于某些原因,当这些选项进入批处理文件以处理等号时,已经转换为空格,现在看起来像:

"batchfile.bat" "--option1 some_value" "--option2 some_other_value\with_a\path"

因此,处理失败。任何想法可能导致等号被空格替换?我正在使用 Qt 下载页面上的 QT 4.6.3 框架的 mingw 构建。

编辑: 这是实际的代码。我没有写它(我是一个完整的 Qt 菜鸟),但我必须尝试让它工作。它是在两个版本的 RHEL(4 和 5)、OS X 和 Windows 上运行的自动化构建系统的一部分。除了 Windows,它在任何地方都可以正常工作。

QProcess sconsProcess;
sconsProcess.setWorkingDirectory(build.getBuildLocation());
sconsProcess.setProcessChannelMode(QProcess::MergedChannels);

qDebug()<<"Starting scons process:"<<build.getSconsLocation()<<QString("--variant=%1-%2").arg(build.getOs()).arg(build.getVariant())<<
          QString("--source-release=%1").arg(build.getSettings().getSetting("sourceReleaseLocation", QStringList()<<"BUILDLOCATION"<<"VERSION",
                    QStringList()<<build.getBuildLocation()<<build.getBuildPackage().getVersion()).toString());
sconsProcess.start(build.getSconsLocation(), QStringList()<<QString("--variant=%1-%2").arg(build.getOs()).arg(build.getVariant())<<
          QString("--source-release=%1").arg(build.getSettings().getSetting("sourceReleaseLocation", QStringList()"BUILDLOCATION"<<"VERSION",
                    QStringList()<<build.getBuildLocation()<<build.getBuildPackage().getVersion()).toString()));
qDebug()<<"Source release build process started";

在 Windows 中转换为的实际值(在第一个 qDebug() 打印调用中打印出来的位)是:

调试:启动 scons 进程:“V:\Glast_Software\Toaster\tools\Python2.5\Scripts\scons-1.3.0.bat”“--variant=Windows-i386-32bit-vc71-Debug”“- -source-release=V:\Glast_Software\Toaster\ReleaseManagerBuild\Windows-i386-32bit-vc71\Debug\ScienceTools\LATEST-1-3163\ScienceTools-LATEST-1-3163-source.zip"

但是在 scons-1.3.0.bat(我让它回显了所有执行的命令)内部,传递的参数看起来像:

"--variant Windows-i386-32bit-vc71-Debug" ""--source-release V:\Glast_Software\Toaster\ReleaseManagerBuild\Windows-i386-32bit-vc71\Debug\ScienceTools\LATEST-1-3163\ ScienceTools-LATEST-1-3163-source.zip"

缺少等号。

编辑(2010 年 6 月 29 日): 我应该补充一点,该系统设计为使用 LSF 批处理排队系统在小型 Windows 批处理场上运行。仅当进程作为批处理作业运行时才会失败。当我在其中一台批处理机器上从命令行运行该程序时,它运行良好,并且完全按照它应该做的那样工作。所以可能是环境问题。

【问题讨论】:

请显示调用QProcess::start() 的实际代码 - 这样我们就不必猜测您可能使用的重载以及引号和其他特殊字符本身是否被引用、转义或其他。 @迈克尔。实际上,我已经尝试过两种重载(命令和参数的一个字符串以及程序的字符串和参数的字符串列表),结果是一样的。我会发布一个示例。 【参考方案1】:

这很有可能是因为引号没有通过(它们可能需要转义,请参阅docs for QProcess::start())。

cmd.exe 将命令行选项中未引用的等号视为类似于空格或制表符的参数之间的分隔符。只是 Windows cmd 脚本中许多奇怪的地方之一:

C:\test>type c:\util\cmdechoargs.cmd
@echo off
setlocal
set /a i=0
echo args[*]: %*
:loop
if %1 ==  goto :eof
echo argv[%i%]: %1
set /a i=%i% + 1
shift
goto :loop


C:\test>cmdechoargs testing=123
args[*]: testing=123
argv[0]: testing
argv[1]: 123

C:\test>cmdechoargs "testing=123"
args[*]: "testing=123"
argv[0]: "testing=123"

我遇到的关于如何在 Windows cmd 脚本中处理命令行参数的最佳文档是 Tim Hill's "Windows NT Shell Scripting" - 只需一分钱就可以使用!

根据您的更新中给出的示例,我认为您可能希望其中包含等号的选项在其中嵌入引号:

"\"--variant=%1-%2\""
"\"--source-release=%1\""

编辑——新材料

下面的脚本有一个例程,它将去掉传递给 cmd 脚本的参数的引号。该例程使用我上面提到的 Tim Hill 书中的成语/技术在名为 RET 的环境变量中返回“取消引用”参数。我从此处的示例中窃取了一些取消引用的代码:http://ss64.com/nt/syntax-esc.html,但使其在处理空引号时更加健壮。

@echo off
setlocal
set /a i=0
echo args[*]: %*
:loop
if %1 ==  goto :eof
echo.
echo argv[%i%]: %1

call :dequote %1
set dequoted_arg=%RET%
echo argv[%i%] ^(dequoted^): %dequoted_arg%

set /a i=%i% + 1
shift
goto :loop


:dequote
setlocal
SET _string=###%1###
if %_string% == ###### goto :dequote_empty
if %_string% == ###""### goto :dequote_empty
SET _string=%_string:"###=%
SET _string=%_string:###"=%
SET _string=%_string:###=%
goto :dequote_done

:dequote_empty
set _string=

:dequote_done
endlocal & (set RET=%_string%) & goto :eof

除了最简单的任务之外,您要避免(在我看来)cmd 脚本的原因就是这种事情。但是,我希望这可以帮助您通过批处理文件将不带引号的参数传递给您的 scons 进程。

【讨论】:

并且在参数周围添加一组额外的转义引号并没有起作用,确实设法将其变成单个参数,并且 = 符号没有消失,但引号随后被传递给 SCons它认为整个事情是一个构建目标,而不是一个选项和价值。 @dagorym:我添加了一个示例,可以在您的 cmd 脚本中去除批处理文件参数的引号。希望对您有所帮助... 我能够使用它来解决问题。谢谢。在让它工作的过程中,我发现了我现在必须运行的执行环境的另一个问题。 :)【参考方案2】:

您是否尝试过转义 = 标志?此外,您示例中的路径肯定需要转义 \ 字符。

【讨论】:

我应该尝试一下,但代码是在 RHEL4、RHEL5、OS X 10.4 和 Windows 上编译的。转义 '=' 会导致 unix 版本出现问题吗? (其中包含路径的条目的值是从存储在 mysql 中的配置中提取的,它似乎没有额外的转义就可以了。 好的,所以您不会按照原始问题中的说明逐字传递字符串。然后请细化您的问题,看起来您想传递一个带有未转义反斜杠的字符串(作为文字字符串对于编译器来说是错误的)。 转义等号的效果完全为零。 :(

以上是关于为啥 QProcess 将我的参数中的“=”转换为空格的主要内容,如果未能解决你的问题,请参考以下文章

为啥扩展语法会将我的字符串转换为数组?

将我的 FBX 文件转换为 .gltf 后,模型非常小,为啥?

为啥 Pandas 将我的 numpy float32 强制转换为 float64?

为啥我不能将我的系统时间设置为接近夏令时转换的时间

为啥 `fetch` 将我的 JSON 字符串转换为查询字符串?副作用? [复制]

为啥我的带有命名参数的查询返回空白结果?