繁体   English   中英

从Powershell调用批处理文件时,插入符号为什么会消失?

[英]Why do carets vanish when calling a batch file from powershell?

这是我的args.bat文件:

@echo off
python -c "import sys; print(sys.argv)" %*

我在这里调用python是因为我确切地知道如何解释输出,而不是猜测字符串中的引号

如果我从cmd调用它,将会发生以下情况:

>.\args.bat ^^^^^
More?
More?
['-c', '^']
>.\args.bat "^^^^^"
['-c', '^^^^^']

但是,这是powershell的作用:

PS> .\args.bat ^^^^^
['-c', '^']
PS> .\args.bat "^^^^^"
['-c', '^']
PS> .\args.bat '^^^^^'
['-c', '^']
PS> .\args.bat "'^^^^^'"
['-c', '^']
PS> .\args.bat '"^^^^^"'
['-c', '^^^^^']

从Powershell调用批处理文件时,为什么必须双引号引用参数?


从powershell调用python并不存在相同的问题:

PS> python -c "import sys; print(sys.argv)" "^^^^^"
['-c', '^^^^^']
PS> python -c "import sys; print(sys.argv)" '^^^^^'
['-c', '^^^^^']
PS> python -c "import sys; print(sys.argv)" ^^^^^
['-c', '^^^^^']

但是从powershell从python调用批处理时仍然存在!

PS> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
['-c', '^']

并从cmd的python批处理:

> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
['-c', '^']

有关批处理文件是否可以可靠地传递任意参数的更大问题(损坏警报:否),请参阅Eric的后续问题


tl; dr

PS> .\args.bat --% "^^^^^"
['-c', '^^^^^']

使用--% (停止分析符号) ,使PowerShell可以按原样传递其余参数,除了扩展cmd.exe样式的环境变量引用(例如%OS%

相反,您将无法引用PowerShell变量或表达式。


PowerShell作为本身的外壳,首先执行其自身的解析,然后(在Windows上这是不幸的必要)在外部程序编写命令行时重新引用

这样做的方式已经随着时间而改变,并且在过去一直是许多问题的根源。 这些问题导致引入--% ,如上所述,但是有其自身的挑战。

但是,考虑到外部程序未必一定会理解PowerShell的语法,通常必须重新报价。
最值得注意的是,不能假定所有外部程序都理解'...'引用,因此需要转换为"..."

但是,PowerShell根据是否认为必要而 有条件地重新报价。

在手的情况下,因为PowerShell中内容 "^^^^^"字符串包含没有空格 ,PowerShell的决定通过批处理文件时,它引用它 ; 即:

.\args.bat "^^^^^"

有效地成为

.\args.bat ^^^^^

这对于大多数外部程序都很好,其中^没有语法含义,但是在批处理文件(由cmd.exe解释)的情况下,它很重要,因为^用作转义符。 以不带引号的字符串存在。

要在这种情况下仍然强制使用双引号,作为上面的--%方法的替代方法,可以使用嵌入式双引号,如您在问题中已经演示的:

PS> .\args.bat '"^^^^^"' #  '...' quoting with embedded "..." quoting
['-c', '^^^^^']

从powershell调用python并不存在相同的问题:
PS> python -c "import sys; print(sys.argv)" "^^^^^"

这是因为在这种情况下不涉及cmd.exe ,即使从PowerShell调用时括起来的双引号丢失了,Python也会将^实例视为文字。

但是从powershell从python调用批处理时仍然存在
PS> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"

然后从cmd的python批处理: > python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"

那是因为您要再次调用一个批处理文件-在这种情况下甚至从cmd.exe ^^^^^使用未引号的 ^^^^^ ,因为封闭的'....'Python仅具有语法意义,并且不会通过-重新介绍了^的特殊解释。

请注意, 即使是调用批处理文件的“无壳”方法(例如Python中的subprocess.call() )也始终会调用cmd.exe ,因为cmd.exe是执行批处理文件所需的解释器。

未加引号的字符串^^^^^传递到批处理文件时,似乎有两轮解释:首先,作为参数解析的一部分,每对^^变为单个^ ,所有不成对的^被丢弃。 因此, 在批处理文件中 ,您会看到^^ ,当不加引号时,它会变成单个^ -如果在批处理文件中对%*%1双引号,则会看到^^被传递。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM