bash shell访问$ ProgramFiles(x86)环境变量

时间:2018-11-30 19:14:55

标签: windows bash git command

在bash外壳中,我正在使用git-bash.exe,如何访问Windows 10 ProgramFiles(x86)环境变量?

如果执行printenv,则会在输出中看到带有大写字母的外壳,但是尝试使用echo $ProgramFiles(x86)echo $ProgramFiles\(x86\)echo $"ProgramFiles(x86)"来访问它。

我可以使用echo $PROGRAMFILES来访问该环境变量的非x86版本,而不会出现任何问题,并进行相关的冒号删除和反斜杠以转发在PATH环境变量更新中使用它所必需的替换,例如PATH=$PATH:"/${PROGRAMFILES//:\\//} (x86)/Some App Path With Spaces/"后跟echo $PATHprintenv PATH,以确认所需的结果。问题是,我宁可不必编写ProgramFiles(x86)环境变量,也不必直接在更新PATH环境变量中使用它。

在尝试使用Windows APPDATA [= C:\ Users \ <用户名> \ AppData \ Roaming]环境变量时,沿着这些相同的行,在更新PATH环境变量时,我需要能够仅替换初始冒号和反斜杠以及后续的反斜杠和正斜杠。使用echo ${APPDATA//:\\//}会产生C/Users\<username>\AppData\Roaming,我不知道如何获取bash环境变量的字符匹配和替换语法以覆盖这两种情况,以便产生在更新PATH环境变量。

2 个答案:

答案 0 :(得分:1)

注意:下面描述的过程中存在缺陷。特别是,如果某些环境变量设置为多行值,其中一条值行与sed表达式匹配,则您还将捕获该行。为了避免这种情况,如果您有Python,可以使用:

python -c 'import os; print(os.getenv("FOO(BAR)"))'

例如。如果未设置该变量,则将打印None,因此,您可能希望将其设置得更漂亮:例如,提供默认值,或者如果未设置该变量,则使用sys.exit(1)。 (但是,如果有可用的Python解释器,则可以考虑使用Python而不是直接使用bash编写。)


Unix shell(sh,bash等)变量名(包括环境变量)被限制为不包含括号的字符集。特别是,"$FOO(BAR)" 总是解析为对变量$FOO的引用,后跟(BAR)作为单独的单词。即使对于大括号的扩展形式也是如此,其中单独的单词(BAR)在语法上是无效的:

bash$ echo "${FOO(BAR)}"
bash: ${FOO(BAR)}: bad substitution

尽管如此, 仍然可以使用其他程序来设置和访问此类变量。例如,使用Python我将 set FOO(BAR)设置为hello

>>> import os
>>> os.environ["FOO(BAR)"] = "hello"
>>> import subprocess
>>> subprocess.call("bash")
bash$

此bash实例无法直接访问该变量,但是env打印所有变量:

bash$ env | grep FOO
FOO(BAR)=hello

如果您有env(可能有)和sed,则可以将它们组合以提取任意变量:

bash$ setting="$(env | sed -n 's/^FOO(BAR)=//p')"
bash$ echo "$setting"
hello

因此,假设Windows Bash没有任何特殊情况可以更好地解决此特定的笨拙问题,则此技巧同样适用于“ ProgramFiles(x86)”。

用正斜杠替换多个反斜杠

您几乎在那儿:问题是您的模式专门针对:\,但是字符串有多个\,但没有冒号。最好的选择可能是拥有一个真正理解Windows路径的程序或函数,因为它们不一定在前面有驱动器号(请参阅https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats)。但是此模式适用于所有反斜杠:

bash$ v='a\b\c'
bash$ echo ${v//\\/\/}
a/b/c

双斜杠表示“替换所有出现的内容”。这样,模式\\,它与一个反斜杠匹配。下一个斜杠引入替换字符串\/,表示一个正斜杠。 (这也可以写成/,但奇怪的是,我发现它更难阅读。)

当然,这不能代替C:中的冒号,因此我们需要再替换一个。您无法在一个${...}扩展中做到这一点,所以诀窍是添加另一个:

bash$ v='C:\a\b\c'
bash$ echo ${v//\\/\/}
C:/a/b/c
bash$ v1="${v//\\//}"; echo ${v1/:/}
C/a/b/c

将其放在shell函数中,您最终可以使它足够聪明以处理所有有效路径,并可以使用local防止变量名v1泄漏。

答案 1 :(得分:1)

关于APPDATA:cygpath程序可以在Windows,Unix和“混合”约定之间转换路径名。 Cygwin和Windows的Git都附带此工具。示例:

$ echo "$APPDATA"
C:\Users\me\AppDataRoaming\
$ cygpath -u "$APPDATA"
/c/Users/me/AppData/Roaming
$ cygpath -m "$APPDATA"
C:/Users/me/AppData/Roaming
$ cygpath -w "$APPDATA"
C:\Users\me\AppData\Roaming

“混合”格式非常有用,因为即使大多数Windows程序和Windows的Git都可以直接处理该格式。

cygpath的输出分配给变量是这样的(请注意引号!):

$ XAPP=$(cygpath "$APPDATA")
$ echo "$XAPP"
$ cd "$XAPP"