在终端处理 NBSP

在终端处理 NBSP

如何在终端中处理 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+ xj

bind -x '"\C-xj": _fix_nbsp'

Ctrl现在您可以通过输入+ x,来清理命令行j

让 Bash 在 时自动执行此操作可能很有用Enter。通常Enter发送Ctrl+ (通过+ ,m验证,您应该会看到),但+也应该可以正常工作。因此,让我们发送+ ,来触发我们的函数,然后发送+来执行结果:CtrlvEnter^MCtrljEnterCtrlxjCtrlj

bind '"\C-m": "\C-xj\C-j"'

Ctrl手动输入+j仍将允许您执行命令行而不调用该函数。请记住,该函数将所有 NBSP 转换为常规空间。如果您的代码包含应该保留的 NBSP,那么您需要手动修复其他(即不需要的)NBSP 并使用Ctrl+执行j

笔记:

  • 为了使解决方案永久有效,请将函数和bind …命令添加到您的~/.bashrc

  • 如果您选择覆盖,Enter那么即使Enter要在引号字符串之后或内部插入换行符\(因此尚未执行),该函数也会运行。只要您希望转换 NBSP,这就不会破坏一切。当最后一次运行单独完成整个工作时,仍然多次运行该函数是不优雅的。另一方面,该函数不会调用外部实用程序sed,而是完全在 Bash 内部完成其工作,因此即使偶尔徒劳地多次调用它也不是那么糟糕。

    但是,如果您在 NBSP 应该保留的位置粘贴多行命令(因此您将使用上述建议的Ctrl+ j),则粘贴的换行符将触发已粘贴片段的功能。要解决此问题,请调查括号内的粘贴

相关内容