gpt4 book ai didi

r - Rscript在带有单引号和双引号的窗口上的行为不一致

转载 作者:行者123 更新时间:2023-12-02 22:09:51 26 4
gpt4 key购买 nike

如果我调用

Rscript -e "print('hello')"
正确打印出答案
[1] "hello"
但是,如果我切换单引号和双引号,它将无法正常工作,并且看起来双引号已被删除:
Rscript -e 'print("hello")'
给出:
Error in print(hello) : object 'hello' not found
Execution halted
请注意,并非Powershell错误地进行了转义。回声仅给出预期的结果:
PS> echo 'print("hello")'
print("hello")
PS> echo "print('hello')"
print('hello')
并且在正确解析两个变体的macO或Linux上未观察到相同的行为。
有趣的是,对于command.com甚至更疯狂:
C:>Rscript -e "print('hello')"
[1] "hello"

C:>Rscript -e 'print("hello")'
[1] "print(hello)"
我的意思是...什么?!?
这里已经提到过:
Single line code to run R code from Windows command line
但没有任何解释。我认为这是Windows上Rscript的错误,但我想听听其他意见。

最佳答案

Dabombber's helpful answer提供了所有指针,但让我尝试从概念上将其简化:
该问题并非特定于RScript.exe,并且可能影响从PowerShell对任何外部可执行文件的调用:
至少在PowerShell 7.0 (本文撰写时为当前版本)中,将带有嵌入式双引号(")的参数传递给外部程序的从根本上破坏了,如GitHub issue #1995中所述;简而言之:PowerShell在幕后为目标程序(进程)构造了一个命令行,该程序仅使用"..."-引用,但忽略了嵌入式逐字"字符。因为它们在语法上有效地包含在此类双引号字符串中。

  • 现在,您必须手动转义嵌入式"字符。作为\"
  • 但是,如果及在修复了该错误后,此解决方法就会中断,因为此修复程序要求自动应用此转义,然后转义逐字\"作为\\\"

  • # WORKAROUND as of v7.0, which will break if and when the problem gets fixed.
    PS> Rscript -e 'print(\"hello\")'
    第三方 Native module (例如,与 Install-Module -Scope CurrentUser Native一起安装)提供 帮助函数ie 补偿了损坏的行为;它是以前向兼容的方式编写的,因此,只要应该修复它,它就可以简单地遵循内置行为:
    # Thanks to `ie`, no workarounds are required.
    PS> ie Rscript -e 'print("hello")'
    至于 临时解决方案-两者都适用于 Rscript.exe,但不能指望它是一个通用的解决方案:
  • 对于同时支持'...'"..."引用的目标程序:交换引号以仅使用嵌入式'字符。,如您的问题所示,但请注意,在PowerShell中'...'"..."字符串的语义不同("..."字符串为expandable (interpolating) strings),并且可能在目标程序中也具有不同的语义(Rscript中不是这种情况):
  • Rscript -e "print('hello')"

  • 对于通过stdin接受输入的目标程序,请使用PowerShell管道,该bug不会浮出水面(尽管请注意,您可能必须将$OutputEncoding首选项变量设置为目标程序期望的字符编码):
  • 'print("hello")' | Rscript -


  • 关于您的观察和 背景信息,包括有关 cmd.exe和POSIX兼容shell的信息:

    Note that it's not powershell doing the escaping incorrectly.


    正如Dabombber所指出的,这是PowerShell的问题,但是仅在调用外部程序时才会出现问题,而 echo是PowerShell本地用户的内置别名。 Write-Output cmdlet(使用 Get-Command echo验证)。
    在Windows上,您可以通过调用 choice.exe(忽略 [Y,N]?N后缀)来查看有缺陷的参数传递的问题,如下所示:
    PS> 'n' | choice /m 'print("hello")'
    print(hello) [Y,N]?N
    带有 choice.exe/m可用于回显一个自变量,因为它将被外部程序接收,并且如您所见,双引号有效地丢失了,因为PowerShell错误地将 print("hello")逐字放在流程命令行上-却没有转义 "字符。 -哪个外部程序将其解析为逐字 print(hello),因为它们允许单个参数由未加引号和双引号的部分组成( print( + hello(去除了句法双引号)+ ))。
  • 如果逐字print(hello)解释为R脚本,它将查找名为hello的变量(对象)-在这种情况下不存在,并触发您看到的错误消息。

  • 在类似Unix的平台(macOS,Linux)上,使用跨平台的 PowerShell [Core] edition/bin/echo 'print("hello")'显示相同的问题。

    And the same behavior is not observed on macOs or Linux, where both variants are correctly parsed.


    是的,如果在那里使用与POSIX兼容的 native shell ,例如 bash,您将获得正确的行为(请参见下文)。

    it's even crazier for command.com:


    顺便说一句:您可能是指 cmd.exe ,它是基于NT的Windows平台上的旧命令处理器(命令提示符),直至当前的Windows 10。
    ( command.com 是已终止的以Windows ME结尾的基于DOS的Windows版本上的命令处理器)。
    仅识别双引号( cmd.exe)来为其自身划定参数边界,而不能识别单引号( "...");无论如何,它实质上都会将原始引用传递给目标可执行文件(在执行其自身对命令行的解释后,例如环境变量扩展)。
    这从根本上不同于PowerShell和POSIX兼容的shell:
  • 在类Unix平台上-兼容POSIX的 shell 可识别'...'-带引号的参数-进程命令行的概念不存在,并且类似POSIX的shell本身已从其命令行中解析出的任何参数都按以下方式传递:是-作为逐字参数数组-目标可执行文件;因此,shell字符串文字'...'"print('hello')"分别作为逐字'print("hello")'print('hello')传递,这按预期工作,假设R也同时识别print("hello")'...'字符串文字。
  • PowerShell也具有"..."字符串(按原样对待它们的内容),但是在Windows上,它会将它们转换为幕后的'...'字符串(如果需要引用),这是从v7.0开始可以出现的上述bug。除了bug之外,这种翻译是有意义的,因为在其他程序的命令行上,仅"..."引用可以被认为具有语法含义(请参阅底部)。不幸的是,PowerShell在类似Unix的平台上做同样的事情,即使它不应该这样做(它构造了一个伪命令行,.NET API然后将其解析为传递给目标进程的逐字自变量数组),因此该错误浮出水面。还有。

  • 因为 "..."保留了原始报价,所以 cmd.exe将命令行 RScript中的 'print("hello")'解释为字符串文字而不是命令,因为它删除了所有 Rscript -e 'print("hello")'字符。在将结果解释为R脚本之前,首先在命令行上使用语法功能(而约定中的 "(单引号)在命令行上没有语法含义):

    因此,
  • '被解析为'print("hello")' + 'print((去除了命令行hello)+ ",导致逐字)被解释为R代码,这是R字符串文字,因此按原样打印(输出使用'print(hello)'引用,但这只是输出格式的人工产物;请注意,无需显式调用"...",表达式的结果(在这种情况下为字符串文字print())将自动打印出来)。
  • 相比之下,'print(hello)'解析为逐字"print('hello')"(除去了命令行print('hello')),由于缺少引号,因此按预期将其解释为命令,即"函数调用。

  • 最终,在Windows上流程命令行解析 的无政府状态中没有硬性规定:最终取决于每个程序来解释其命令行- this answer包含出色的背景信息。
    但是,幸运的是, 广泛遵守约定,该约定在MS C/C++/。NET编译器和 documented here中实现。
    不幸的是,由于上述错误,从PowerShell 7.0开始,PowerShell不遵守这些约定。由于该错误自v1以来就已经存在,因此用户已经学会了解决方法,例如使用手动 print() -escaping,如上所述。问题是修复该错误将破坏所有解决方法。现在考虑最早以v7.1的形式将修补程序实现为 experimental feature-请参见 this PR on GitHub和相关讨论 here,这表明,除了实现广泛建立的约定外,还应为调用批处理文件和 \"提供便利风格的程序,具有非常规的报价要求。

    关于r - Rscript在带有单引号和双引号的窗口上的行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62954030/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com