从Windows PowerShell运行node.js脚本时未正确解释参数转义
给定以下脚本:从Windows PowerShell运行node.js脚本时未正确解释参数转义,node.js,windows,powershell,yargs,Node.js,Windows,Powershell,Yargs,给定以下脚本: const yargs = require('yargs'); const argv = yargs .usage('Usage: $0 [--whatIf]') .alias('d', 'directory') .alias('wi', 'whatIf') .nargs('d', 1) .describe('d', 'alphabetize this directory')
const yargs = require('yargs');
const argv =
yargs
.usage('Usage: $0 [--whatIf]')
.alias('d', 'directory')
.alias('wi', 'whatIf')
.nargs('d', 1)
.describe('d', 'alphabetize this directory')
.describe('whatIf', 'show what would happen if run')
.demandOption(['d'])
.argv;
console.log(argv.directory);
如果我像这样从Windows PowerShell调用脚本:节点。\alphalizer.js-d'l:\my folder\Files-Some Files In Here\'--whatIf
我会得到输出l:\my folder\Files-Some Files In Here\“--whatIf
我只希望l:\my folder\Files-这里有一些文件\
。对于不需要转义的文件夹名,它可以正常工作,但转义似乎会让它感到困惑
如果我检查process.argv
,我可以看到相同的转义问题
我注意到,如果我删除尾部斜杠,它将起作用。但是,这仍然指向节点脚本没有正确处理输入,因为在字符串由单引号设置的情况下,这是不必要的
有什么方法可以让这项工作正常吗?在正确引用外部程序的参数方面,Windows PowerShell(
PowerShell.exe
)和PowerShell[Core]v6+(pwsh
)都从根本上被破坏了-请参阅以获取背景信息
一般来说,Windows上的PowerShell必须在后台执行重新引用,以确保只使用“…”
-quoting,因为在解析命令行(在Windows上,每个程序都必须自己执行)时,不能假设外部程序也能理解“…”
-quoting
对于以\
结尾并带有嵌入空格的参数,Windows PowerShell更容易损坏,重新引用时不正确;e、 g:
PS> foo.exe 'c:\foo \' bar
在幕后转换为以下命令行:
foo.exe "c:\ foo \" bar
这是错误的,因为大多数应用程序(包括PowerShell的应用程序)明智地假设\“
是一个转义的”
字符。一字不差地说,尽管形式上没有结束语,“
,但认为参数继续以条
结尾,然后隐式结束
PowerShell[Core]v6+更合理地将上述内容转换为foo.exe“c:\foo\\\”条
,其中\\
被解释为转义的\
,以下“
再次具有语法功能
如果您一直使用Windows PowerShell,您唯一的选择是:
- 或者:如果可能,请去掉尾随的
\
- 否则:手动将其加倍(
),但仅当参数还包含空格时才执行此操作(否则,\\
将按原样保留,尽管在文件系统路径通常是良性的情况下)\
“
不是Windows文件名中的非法字符吗?也许在\”
上拆分是合理的?不确定这是否会破坏我在其他操作系统上的脚本。由于制表符补全在默认情况下会添加一个尾随斜杠,所以要记住这一点有点恼人。@Casey,是的,“
不是文件名中的法定字符,但并非每个参数都是且可以假定为文件名;给定运行时的命令行解析器无法做出这样的假设,因为它不知道参数最终代表什么。当然不知道,但我正在考虑为我自己的脚本提供一种解决方案,我知道它是我想要的文件名。当然,这并不能解决这个问题,因为它还吞噬了其他参数。@Casey,我听说你是tab completion,但真正让人恼火的是Windows PowerShell在这方面一直处于崩溃状态。试图弥补从脚本内部传递参数的错误方式听起来是一项痛苦而不平凡的任务,可能需要您获取原始命令行并执行自定义解析-不确定这是否值得。@Casey:看看您的具体案例:有这么几个选项,也许修复脚本中的问题是可行的,毕竟:按“
拆分argv.directory
,将\
附加到前面的部分(如果需要),并将其用作dir.path;从后面的部分中修剪前导空格,并手动将其作为选项名解析。