在 msys bash 上,当包含换行符时,PS1 命令替换会失败。

19

这个命令执行成功

$ PS1='$(date +%s) $ '
1391380852 $

但是如果我添加一个换行符,它就失败了

$ PS1='$(date +%s)\n$ '
bash:command substitution:第1行语法错误,附近有意外的符号 `)'
bash:command substitution:第1行:`date +%s)'

如果我使用反引号,则可以正常工作

$ PS1='`date +%s`\n$ '
1391381008
$

但是不鼓励使用反引号。那么是什么导致了此错误?

GNU bash,版本4.2.45(6)-release

3
对我来说它正常运行。你使用的是哪个Bash版本?我安装了“GNU bash,version 4.2.45(2)-release”。 - Rubens
2
这对我也起作用,即使在bash 3和KSH中也是如此(除了KSH中的\n)。 - Idriss Neumann
这是特定供应商软件包的4.2.45(6),还是原始上游版本? - Charles Duffy
很难想象一个跟在右括号后面的字符会导致该右括号被视为命令替换的文字部分,而不是命令替换的结束标记。解析必须是复杂的,需要在流中进行向后跳转或者奇怪的前瞻。 - Kaz
@Kaz,))是与)不同的标记,因此需要一定程度的前瞻。但是,是的,这很有趣--它依赖于平台使其变得更加有趣。 - Charles Duffy
这是一个奇怪且晦涩的问题。多年后,我在Windows上的Git bash中遇到了类似的问题... 我只好使用反引号。如果它能工作... - spechter
3个回答

26

你可以轻松消除歧义解析,以防止遇到任何此类错误(虽然我自己无法复制它):

您可以轻松进行歧义消除解析,以防止遇到任何类似问题(尽管我自己无法重现该问题):

PS1='$(date +%s)'$'\n$ '

这个 $'\n' 语法解析为一个文字换行符,而 '\n' 解析为包含两个字符的字符串 \n 转义序列。

有关 $'' 如何与 '' 不同(展开反斜杠转义序列)的更多信息,请参阅 Bash Hackers Wiki


2
运行得非常好。在我的情况下,问题出现在使用MSYS2编译的bash (GNU bash, version 4.2.45(6)-release (x86_64-pc-msys)上。谢谢。 - Matt
2
好的,我已经解决了双引号的问题。"bla \n bla" 现在变成了 "bla "$'\n'" bla"。通过一些试错和阅读 Bash 转义方面的知识解决了这个问题... - JustGoscha
1
@oligofren,需要记住的一件事是,shell不要求一个单词在整个过程中都使用相同的引号风格;例如,您可以使用literal"double-quoted"'single-quoted'来生成一个单词,该单词的不同部分在解析时使用三种不同的引号类型进行处理。这正是我在答案中所做的,切换到$''引号类型以注入一个字面上的换行符。 - Charles Duffy
1
@oligofren,这是一种不同的引用形式,会导致解析方式不同。$'\n' 解析为一个字符的换行符,而 '\n' 解析为两个字符的序列,即一个字面上的反斜杠后跟一个字面上的 n - Charles Duffy
1
谢谢您,希望现在应用的编辑符合您的要求。 - Charles Duffy
显示剩余14条评论

3

当我在Windows上的bash(MSYS2)中尝试将.git-prompt包含在我的PS1中时,遇到了类似的问题。问题在于\n,如果我将其移除,一切都能正常运行,但我想要换行。

顺便说一下,在Linux上一切正常。

bash的版本是:4.3.42(5)-release (x86_64-pc-msys)

旧的、有问题的PS1:

PS1='\e[32m\]\u@\h \e[36m\]\w \e[32m\]$(__git_ps1 "(%s)")\nλ \e[0m\]$(tput sgr0)'

修复:

PS1='\e[32m\]\u@\h \e[36m\]\w \e[32m\]$(__git_ps1 "(%s)")'$'\nλ \e[0m\]'

抱歉,您没有提供需要翻译的内容。请提供需要翻译的原始文本。
PS1='\u@\h \w $(__git_ps1 "(%s)")'$'\n$ '

感谢Charles Duffy找到了这个问题!


1
< p >在我的git-bash Windows VSCode终端中,$'\n' hack仍然导致语法错误。经过多次尝试,我成功通过使用换行符的八进制等价形式\012进行修复。< /p > < p >简而言之,在任何导致语法错误的地方,将\n替换为\012。< /p >

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接