gpt4 book ai didi

node.js - 有没有办法防止Windows命令行中的env变量扩展百分比?

转载 作者:可可西里 更新时间:2023-11-01 14:43:40 24 4
gpt4 key购买 nike

我在Windows上的git bash中使用以下git命令:

git log --format="%C(cyan)%cd%Creset %s" --date=short -5

它显示提交日期( %cd),然后显示提交消息( %s)。提交日期用颜色标记包裹: %C(cyan)开始彩色输出, %Creset停止彩色输出。

虽然它在git bash中可以正常工作,但它与 cmd结合使用效果并不理想: %cd%由Windows Shell扩展到当前工作目录(相当于bash中的 $PWD)。

因此,当通过cmd运行该命令时,我看到在第一列中显示了当前工作目录,而不是提交日期!
git bash:
2015-10-08 commit msg
2015-10-08 commit msg
2015-10-07 commit msg
2015-10-06 commit msg
2015-10-06 commit msg

命令:
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg

实际上,我从来没有直接自己使用 cmd,而是在编写其中包含以下内容的nodejs(0.12)脚本时发现了此行为
require('child_process').execSync('git log --format=...', {stdio: 'inherit'})

在Windows上由 Node 使用 cmd执行)。

一个简单的解决方法可能是引入一个空间以防止 %cd%被发现,即更改
git log --format="%C(cyan)%cd%Creset %s" --date=short -5


git log --format="%C(cyan)%cd %Creset%s" --date=short -5

但是,这引入了一个冗余空间(我在 %s之前删除了另一个空间,但它仍然是一个hack,需要手动干预)。

有没有办法防止Windows Shell扩展?

我有 found有关使用 %%^%逃脱 %的信息,但它们不是此处的解决方案:
# produces superfluous ^ characters
git log --format="%C(cyan)^%cd^%Creset %s" --date=short -5

^2015-10-08^ commit msg
^2015-10-08^ commit msg
^2015-10-07^ commit msg
^2015-10-06^ commit msg
^2015-10-06^ commit msg

# seems the expansion is done at command parse time
git log --format="%C(cyan)%%cd%%Creset %s" --date=short -5

%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg

理想的解决方案应该是与bash和cmd兼容,而不产生多余的字符,或者是javascript中的转义函数,以转义Windows的通用UNIX-y命令以防止扩展(如果可以创建这种转义函数)。

最佳答案

提供MC ND's helpful answer的替代方法:

如果您确实需要让 shell 涉及(这不太可能,因为您声明您希望该命令同时与Windows的cmd.exe和Bash一起使用),请立即考虑下面的解决方案;请参见下面的解决方案。有关绕过问题的无 shell 替代产品的信息,请参阅底部的解决方案。

MC ND的提示,是通过建议在%实例周围放置双引号而不是%实例之间的潜在变量名称来改进我的原始方法,并建议对execFileSync进行说明。

“转义” %字符。用于cmd.exe
MC ND's answer中所述,从技术上讲,您不能在Windows命令提示符处转义%(在批处理文件中,您可以使用%%,但这在从其他环境(例如Node.js)中调用Shell命令时不起作用,并且通常无法跨平台)。

但是,解决方法在每个%实例周围加上双引号:

// Input shell command.
var shellCmd = 'git log --format="%C(cyan)%cd%Creset %s" --date=short -5'

// Place a double-quote on either end of each '%'
// This yields (not pretty, but it works):
// git log --format=""%"C(cyan)"%"cd"%"Creset "%"s" --date=short -5
var escapedShellCmd = shellCmd.replace(/%/g, '"%"')

// Should work on both Windows and Unix-like platforms:
console.log(require('child_process').execSync(escapedShellCmd).toString())

插入的双引号可防止cmd.exe将诸如%cd%之类的标记识别为变量引用("%"cd"%"不会扩展)。

之所以可行,是因为当目标程序处理完多余的双引号后,它们最终会从字符串中删除:
  • Windows :git.exe(大概是通过C运行时)然后负责从组合字符串中除去多余的双引号。
  • (类似于Unix的)(类似于POSIX的shell,例如Bash):shell本身负责在将双引号传递给目标程序之前删除双引号。
  • 注意:通常,在命令中使用双引号意味着您需要注意类似POSIX的shell,它们会对$前缀的 token 执行可能不需要的扩展(此处不存在问题);但是,为了保持Windows兼容,您必须使用双引号。

  • 从技术上讲,将此技术应用于双引号字符串会把它分成一系列双引号子字符串,并散布在未加引号的%实例中。类似于POSIX的shell仍将其识别为单个字符串-子字符串被双引号引起来,并直接邻接%实例。 (如果将这种技术应用于未加引号的字符串,则逻辑相反:实际上是在双引号%实例中进行拼接。)子字符串周围的双引号被认为是语法元素,而不是字符串的一部分。然后在子字符串连接在一起以形成单个文字并传递给目标程序时将其删除。


    通过完全避免使用 shell 来绕过该问题

    注意:以下内容基于execFile[Sync]构建,仅适用于调用外部可执行文件(在OP的情况下是正确的:git.exe)-相反,对于调用shell内置程序(内部命令)或Windows批处理文件, exec[Sync],并因此由cmd.exe解释(在Windows上)。[1]

    如果您使用 execFileSync 而不是execSync,那么 shell 程序(在Windows上为cmd.exe)将不涉及,因此不必担心转义%字符。就此而言,或任何其他shell元字符:
    require('child_process').execFileSync('git', 
    [ 'log',
    '--format=%C(cyan)%cd%Creset %s',
    '--date=short',
    '-5' ], {stdio: 'inherit'})

    请注意,必须如何分别将参数作为数组的元素提供,并且没有嵌入的引号。

    [1]在Windows上,无法直接使用execFile[Sync]调用脚本文件(例如Python脚本),而是可以将解释器可执行文件(例如python)作为要执行的文件,而将脚本文件作为参数。在类似Unix的平台上,您可以直接调用脚本,只要它们具有shebang line并被标记为可执行文件即可。execFile[Sync]可以用来调用Windows批处理文件,但是cmd.exe总是像exec[Sync]一样对参数进行插值。

    关于node.js - 有没有办法防止Windows命令行中的env变量扩展百分比?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33016094/

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