如何在终端中处理 NBSP?
以下是我将完全相同的字符串(由前导 NBSP 组成)粘贴到终端的行为:
$ echo abc
bash: echo: command not found
$ echo abc
abc
$ echo abc
-bash: $'\240echo': command not found
$ ls ~/.inputrc
ls: cannot access '/root/.inputrc': No such file or directory
$ ls ~/.bash*
/root/.bash_history /root/.bashrc
$ cat ~/.bashrc
. . . basically nothing there . . .
$ bind -v | grep bracketed
set enable-bracketed-paste on
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux bullseye/sid
Release: testing
Codename: bullseye
$ uname -rm
5.10.0-6-amd64 x86_64
NBSP 来自我正在使用的文档,无论是 LibreOffice Writer 还是 google doc 等。所以我非常需要让这个粘贴 NBSP 工作(作为我的第二种情况),因为那是我记录命令的地方,即我无法改变它们的行为。
所以,
- 对于这三种情况,我都没有改变任何系统默认设置或我的
- 在我的第二个案例中,也就是有效的案例中,我有
LANG=C
。其他两个案例都基于 utf8LANG
- 但是,即使我
LANG=C
在其他两个中更改为,我仍然会收到相同的错误
“方法 1”来自这个答案对我来说不起作用:
而且这种bind '"\302\240":" "'
方法对我来说也不起作用(这是一台root
目前只有用户的新机器,因此提示可能看起来很奇怪):
我猜测bind '"\302\240"
这与在终端中按下该键有关,而我只是粘贴进去。只是猜测。
$ echo $'\240echo abc' | grep -a $'\240'`
echo abc
nbsp=`echo $'\240'`
$ echo "${nbsp}echo abc${nbsp}${nbsp}${nbsp}def" | grep -a $'\240'
echo abc def
bind "${nbsp}":" "
# then paste in the above echo output,
$ od -c -
echo abc def
0000000 240 e c h o a b c 240 240 240 d e f \n
# paste again to bash, which will become:
$ echo abcdef
abcdef
# i.e., all the spaces have been eaten, instead of mapped as " "
$ tail -5 /etc/inputrc
# map NBSP to regular space (left part has NBSP in quotes, right part has space)
"\240":" "
"\302\240":" "
"Â ":" "
$ tail -4 /etc/inputrc | od -c -h
0000000 " \ 2 4 0 " : " " \n " \ 3 0 2
0000020 \ 2 4 0 " : " " \n " 302 240 " : "
0000040 " \n " 342 220 243 " : " " \n
以上所有命令均在 中完成xterm
,除黑屏命令外,它是来自urxvt
(提供302 240
od -c -
输出)。
结论:
非常感谢 Kamil 的持续帮助。“我住的地方现在是午夜””他说,但继续说道“我将在几个小时内检查这个问题”. 这是精确的绑定命令,这bind 'set enable-bracketed-paste off'
就是我需要的最后一英里。
bind -r '\240'
bind '"\240":" "'
bind 'set enable-bracketed-paste on'
$ echo abc def
-bash: $'\240echo': command not found
bind 'set enable-bracketed-paste off'
$ echo abc def
abc def
抱歉,卡米尔,我应该更加小心地按照你的建议去做。
答案1
初步说明
- 此答案适用于编码为
\302\240
(八进制表示)的 NBSP。\302\240
适用于 Unicode。在 iso8859-1 中,它是唯一的\240
(\xa0
,请参阅这个答案)。如有必要,调整解决方案。 - 我的解决方案会影响涉及 Readline 的交互式使用。它们不会修复脚本中不需要的 NBSP。如果您需要修复脚本,请使用
sed
或其他任何方式来实际修复脚本中的代码。 - 解决方案应该适用于键入的命令。对于粘贴的命令,如果
enable-bracketed-paste
是,它们将起作用off
(选中bind -v | grep bracketed
)。覆盖的解决方案Enter将在键入时起作用Enter,即使命令enable-bracketed-paste
是并且是粘贴的。on
全球解决方案
从这个答案在 Ask Ubuntu 上:
将以下内容放入
.inputrc
[…]:[…]
# map NBSP to regular space (left part has NBSP in quotes, right part has space) " ":" "
如果 markdown 搞乱了上述内容
确实如此!
如果 markdown 搞乱了上述内容,则必须将 NBSP 放在冒号左侧的引号中,如注释中所述。这会将输入流中出现的任何 NBSP 映射到常规空格。
readline 应该明白\302\240
。下面的版本不会被 markdown 破坏,你可以直接复制它:
"\302\240":" "
请注意,此解决方案可能会影响任何使用 Readline 的程序,并且可能没有简单的方法可以根据程序的需求禁用该解决方案。在 Bash 中,您可以通过运行以下命令来禁用它:
bind -r '\302\240'
并通过以下方式重新启用:
bind '"\302\240":" "'
Bash 的单独实例可以独立禁用绑定。
仅适用于 Bash
如果您想要影响 Bash 但不影响使用 Readline 的其他程序,那么请不要修改您的.inputrc
;而是将其放入您的~/.bashrc
:
bind '"\302\240":" "'
禁用和重新启用的命令与之前的解决方案完全相同。
动态地
此函数将把命令行中的所有 NBSP 转换为常规空格:
_fix_nbsp () { READLINE_LINE="${READLINE_LINE//$'\302\240'/ }"; }
将其绑定到一些未使用的组合,例如Ctrl+ x,j:
bind -x '"\C-xj": _fix_nbsp'
Ctrl现在您可以通过输入+ x,来清理命令行j。
让 Bash 在 时自动执行此操作可能很有用Enter。通常Enter发送Ctrl+ (通过+ ,m验证,您应该会看到),但+也应该可以正常工作。因此,让我们发送+ ,来触发我们的函数,然后发送+来执行结果:CtrlvEnter^M
CtrljEnterCtrlxjCtrlj
bind '"\C-m": "\C-xj\C-j"'
Ctrl手动输入+j仍将允许您执行命令行而不调用该函数。请记住,该函数将所有 NBSP 转换为常规空间。如果您的代码包含应该保留的 NBSP,那么您需要手动修复其他(即不需要的)NBSP 并使用Ctrl+执行j。
笔记:
为了使解决方案永久有效,请将函数和
bind …
命令添加到您的~/.bashrc
。如果您选择覆盖,Enter那么即使Enter要在引号字符串之后或内部插入换行符
\
(因此尚未执行),该函数也会运行。只要您希望转换 NBSP,这就不会破坏一切。当最后一次运行单独完成整个工作时,仍然多次运行该函数是不优雅的。另一方面,该函数不会调用外部实用程序sed
,而是完全在 Bash 内部完成其工作,因此即使偶尔徒劳地多次调用它也不是那么糟糕。但是,如果您在 NBSP 应该保留的位置粘贴多行命令(因此您将使用上述建议的Ctrl+ j),则粘贴的换行符将触发已粘贴片段的功能。要解决此问题,请调查括号内的粘贴。