我在 Windows 上有几个 Bash 脚本,有时我将它们从 Notepad++ 复制到 WSL(基于 CMD)终端仿真器(TTY)来执行它们。
问题:
尾随空格当我通过以下命令将脚本复制并粘贴到 WSL Nano 中时,每个脚本都会添加(nano 中的绿色框):
nano ~/script.sh
这些尾随的空格字符不是脚本的一部分,实际上会破坏其在 Linux 中的执行,因此不应该出现在脚本中。
WSL TTY 窗口越窄,粘贴时形成的回车符就越多。
脚本一直包含这些绿色盒子当我用 Nano 打开它时,它似乎不会在保存文件时删除这些字符(应该如此),所以有人可能会声称这是 Nano 中的一个错误,但事实上dos2unix
在文件上执行也不会删除尾随的空格。
期望的情况:
我希望将 Bash 脚本(或任何其他数据)从 Windows 复制并粘贴到 WSL Nano 中时,复制过程中不会形成任何尾随空格。
更多信息:
https://github.com/Microsoft/BashOnWindows/issues/2006
https://savannah.gnu.org/bugs/?50879
如果你尝试在 WSL 中重现此问题:
- 确保从 Notepad++ 复制一个脚本,该脚本具有 Unix EOL(LF),并且仅包含制表符缩进。
- 确保您的 nano 脚本文件以 结尾
.sh
,这样您就会有 Bash 高亮显示。如果您仍然没有,请尝试通过 SSH 隧道连接到远程 Ubuntu 服务器(如果有),并以相同的方式在那里创建一个脚本文件,然后您肯定会看到这种行为。 - 无论哪种方式,请确保您的 Nano 窗口很窄(约占视口的 25-50%)并且粘贴了大部分文本。
答案1
正如您所说,问题源于在带有 Unix 行尾(LF)的窄窗口中粘贴文本。
考虑使用以下自动热键脚本“输入”剪贴板文本,让 Windows 处理换行符。
SendMode Input ; Recommended for superior speed and reliability.
; Upon pressing Ctrl+Alt+v
^!v::
; SendRaw "types" the contents of the variable. When it encounters either
; Cr (`r) or Lf (`n), it sends an "Enter", thus CrLf sends Enter twice.
; Replace any CrLf with Lf (ironic, I know), leaving the clipboard as is
newClip := StrReplace(clipboard,"`r`n","`n")
SendRaw %newClip%
return
答案2
按照 Nano 开发团队的 Benno Schulenberg 的建议,在 /etc/nanorc 末尾添加以下代码可以解决这个问题:
bind ^J enter main
一方面,这将禁用尾随空格的形成,另一方面,将向从 Windows 复制的数据添加换行符(LF 字符),因此它不会出现在一长行中。
答案3
在广角图中您展示了:....
...cd maldetect-* &&␠|<-window boundary
bash ./install.sh
(竖线前的字符是 HTML ␠ 或 unicode 字符 U+2420(空格符号)。
该空间应该(必须)在那里。如果窗口边界不在那里,那么该行将是:
...cd maldetect-* && bash ./install.sh
如果没有空格,那么 && 和 'bash' 单词的开头之间就不会有空格——这不应该如果您在 bash 中运行,则会受到伤害,但这只是一个例子......即通常双 & 符号和空格之间会有一个空格。
如果您的空格应该在那里,那么可能导致您出现问题的原因是什么... 嗯.... ARG!您正在将其粘贴到... bash... 哦哦...
如果您要粘贴到 bash 中,由于几年前对自动完成功能进行了更改,bash 在粘贴方面存在“缺陷”(个人观点)。如果您粘贴的文本中包含任何“TAB”(是的,缩进),它将调用 bash 的“自动完成”功能(我对此抱怨过,但有人告诉我没有人将文本粘贴到 bash 中……咳嗽,咳嗽)(抱怨'[电子邮件保护]列表'(尽管我怀疑它很快就会被修复)。当它调用自动完成功能时——很多时候它会吞掉你粘贴的文本的下一个字符,因为它会问一个问题:
> ls <'complete-key' pressed>
Display all 199 possibilities? (y or n)
通常,这会破坏粘贴的文本。无论如何,这对我来说不是问题,因为我的制表符通常位于空白行上(因为它们是缩进代码)。以前有一个选项可以忽略空白行上的代码完成按下(@ 行首或按下的位置前只有空格)。这已更改为仅忽略空命令行(不是空的 tty 行)上的完成字符。将多个命令粘贴到输入中通常被视为 bash 的某种连续命令——而不是空的命令行。不用说,这会导致很多问题。
对我来说,一个不完美的解决方案是将代码完成键从 TAB 重新映射到 Backquote(") (above tilde key). (same bug occurs if you have
在您的文本中为“”,但对我来说,我使用它的频率比 TAB 要低得多)。它设置在主目录的“.inputrc”文件中,该文件控制“readline”(bash 用于读取行、允许编辑等)的行为方式。特别是,我的“.inputrc”中的一个部分具有特定于 bash 的配置选项:
$if bash
# use backquote as completion (yes, that's shift-'~')
# not ideal, but quickest "hack" to get mostly
# transparent pasting (backquote isn't used nearly as often as TAB)
TAB:tab-insert
"`":complete
$endif
替代方案:1)在粘贴之前将所有制表符转换为空格,这样 TAB 就不会触发命令完成。2)始终将文本写入文件并将文件作为源 (.) 或使其可执行并在第一行添加'#!/bin/bash'以使其成为 shell 脚本。
理论上您还应该能够关闭命令完成功能,但我使用得太多了,所以从来没有尝试过。
我现在通常的做法是,在一个窗口(通常是 gvim)中编辑脚本,然后在启动 gvim 的窗口中运行脚本的连续迭代 —— 从而避免“粘贴”。这当然不是我的第一选择,但是 bash 会在完成键后吞掉所有内容,从而破坏输入,这促使我朝这个方向发展。
请注意,如果您将此报告为错误,请准备好提供解决方案!;-) 这就是问题所在:
> ls \<carriage return>
>> [here people want to be able to hit 'TAB' and get an autocomplete of
of the files in the current directory. It looks like an empty line,
but it is a really a continued command line from the previous line.
当您将命令粘贴到 bash 中时,也会发生同样的事情...有些命令会出现您不想要的选项卡...
(Ps 希望这会有所帮助,我并没有完全偏离主题,但是当你提到“粘贴”并且它看起来像 bash 脚本时......并且你提到使用制表符(也会粘贴进去),听起来就像我遇到的完全相同的问题。
使用反引号作为完整的键有时会有点尴尬,但是,粘贴的文本中经常会有制表符……哦,好吧)