如何让长命令行换行到下一行?

Bri*_*anH 122 command-line bash

我在 Ubuntu 中注意到很长一段时间让我感到沮丧的事情是,当我在命令行中输入一个比终端宽度更长(更宽)的命令时,而不是换行到新行,它会回到同一行的第 1 列并开始覆盖我的命令行的开头。(它实际上并没有覆盖实际的命令,但在视觉上,它覆盖了显示的文本)。

没有看到它很难解释,但假设我的终端有 20 个字符宽(我的更像是 120 个字符 - 但为了举个例子),我想呼应英文字母。我输入的是这样的:

echo abcdefghijklmnopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

但是在我按下键之前我的终端是这样的:

pqrstuvwxyzghijklmno
Run Code Online (Sandbox Code Playgroud)

当我按回车键时,它会回响

abcdefghijklmnopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

所以我知道命令已正确接收。它只是在“o”之后包装了我的打字并在同一行重新开始。

如果我在只有 20 个字符宽的终端上输入这个命令,我希望会发生什么:

echo abcdefghijklmno
pqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

背景:我使用 bash 作为我的 shell,我的 ~/.bashrc 中有这一行:

set -o vi
Run Code Online (Sandbox Code Playgroud)

能够使用 VI 命令在命令行中导航。我目前使用的是 Ubuntu 10.10 服务器,并使用 Putty 连接到服务器。

在我工作过的任何其他环境中,如果我输入一个长命令行,当我的命令变得比终端宽度长时,它会在我正在处理的行下方添加一个新行,并且当我继续输入时,我可以看到我的命令2条不同的线路。但是只要我记得使用 Ubuntu,我的长命令只占 1 行。

当我返回历史记录中的前一个命令时也会发生这种情况(我点击 Esc,然后按“K”返回到前一个命令) - 当我到达一个比终端宽度长的前一个命令时,命令行会得到受损,我无法告诉我在命令中的位置。

我发现看到整个长命令的唯一解决方法是点击“Esc-V”,这会在 VI 编辑器中打开当前命令。

我认为我的 .bashrc 文件中没有任何奇怪的东西。我注释掉了“set -o vi”行,但问题仍然存在。

我下载了一个新的 Putty 副本并且没有对配置进行任何更改 - 我只是输入了我的主机名进行连接,但我仍然有问题,所以我认为这与 Putty 无关(除非我需要进行一些配置更改)

有没有其他人遇到过这个问题,谁能想到如何解决它?

编辑

这是我的 .bashrc 文件。我已经在机器之间复制了相同的配置文件,并且我在 $PS1 中使用了特殊字符,这些字符以某种方式将其丢弃。我现在坚持使用 $PS1 的标准 bash 变量。

感谢@ændrük 关于 .bashrc 的提示!

...结束编辑...

gei*_*rha 159

确保 PS1 中所有不可打印的字节都包含在\[ \]. 否则,bash 会将它们计入提示的长度。它使用提示的长度来确定何时换行。

比如这里bash把提示算作19列宽,而终端显示的提示只有10列宽(My prompt青色,>默认颜色):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10
Run Code Online (Sandbox Code Playgroud)

而在这里它只将提示计算为 10 列宽,因为它忽略了特殊\[\]转义之间的字节:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10
Run Code Online (Sandbox Code Playgroud)

但是,对于良好的实践,使用tput生成终端转义而不是硬编码它们:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'
Run Code Online (Sandbox Code Playgroud)

请参阅http://mywiki.wooledge.org/BashFAQ/053以及http://wiki.bash-hackers.org/scripting/terminalcodes了解更多关于 的信息tput

  • 这是对接受的答案没有提供的问题的一个很好的解释 (3认同)
  • @andrybak,它们确实阻止了 `$cyan` 和 `$reset` 被替换,但是每次打印提示时都会评估 `PS1`。您可以通过尝试 `PS1='$var> '` 来看到这一点,然后给 `var` 提供各种值并查看提示如何变化。然后尝试 `PS1="$var> "` 并注意提示保持不变;`$var` 在赋值期间被扩展,而不是每次评估 `PS1` 时。 (3认同)

小智 60

我猜你已经配置PS1了颜色,对吧?

只要确保\[在您PS1的颜色集之前有您的报价

例如:

PS1='\[\e[0;32m\u@\w/:\[\e[m '
Run Code Online (Sandbox Code Playgroud)

  • 在使用简单引号时使用 \\[ 会产生意外的斜线。此外,应该在神奇字符的末尾使用 \],如最佳投票答案中所述 (3认同)
  • -1 不起作用。您需要*包装*非打印部分,开头是`\[`,结尾是`\]`。 (3认同)
  • 哇。我一直在使用终端提示,以前从未遇到过这个问题。永远不会想到这一点。谢谢。 (2认同)

小智 15

我有一个类似的问题,终于找到了一个简单的解决方案。

在您的.bashrc文件中添加以下行:

COLUMNS=250
Run Code Online (Sandbox Code Playgroud)

然后键入source ~/.bashrc以获得所需的效果。

  • 我发现因为我没有为我的 bash 设置 shopt `setwinsize`,所以它没有正确更新 COLUMNS,请参阅 http://unix.stackexchange.com/a/167911/8337 (2认同)

小智 7

一个简单的做法是在设置 PS1 之前添加以下行:

stty columns 1000
Run Code Online (Sandbox Code Playgroud)

例如,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '
Run Code Online (Sandbox Code Playgroud)

然而,这确实会影响其他 UNIX 命令,如 ls 和 man。

  • 这也会严重影响 vim。请不要使用这个。 (4认同)

小智 5

即使我在\[\]分隔符中包含颜色代码,我也遇到了与自定义彩色提示相同的问题。事实证明,bash 在从函数内部回显颜色时存在问题。我最终只为我的提示使用了变量,虽然我的 .bashrc 不太优雅,但现在一切都很好。