介绍
考虑这样的工具watch
可以接受另一个命令(例如ls -l
),如下所示:
watch ls -l
# or equivalently
watch 'ls -l'
如果命令更复杂,如果当前 shell 或 get to 解释诸如$variable
、*
、或之类的内容|
,则全部是关于引用/转义。这两个命令是不同的:;
&&
watch
watch echo "$$"
watch 'echo "$$"'
这些也是:
watch date ; echo done
watch date \; echo done
ssh
类似,它可以接受一个或多个参数并构建一个要在服务器上运行的命令。$variable
如果本地 shell 解释等|
,或者远程 shell,这取决于引用/转义。
并且有些命令sh -c
需要包含代码的单个参数,但引用/转义的需要是相似的。事实上watch
(or ) 为或类似命令ssh
构建了这个单一参数。sh -c
问题
我已经有了要提供给or或类似工具的确切命令。该命令是从历史记录中获取的,或者粘贴到命令行中,或者像要直接执行一样键入;它在我的命令行中逐字记录。命令中的任何内容都不应在到达或类似工具之前进行扩展或解释。在这种情况下,意味着所有的扩展和解释都应该在以后定期发生。在这种情况下,这意味着它应该发生在服务器上。watch
ssh
watch
watch
ssh
现在我需要做两件事:
watch
在开头添加(或其他)。这不是问题。我可以最后做到这一点。引用和/或转义原始命令。通常,该命令可以包含单引号,因此盲目地使用单引号并不是解决方案。我想我知道正确的通用解决方案:
'
用'"'"'
或替换每个'\''
,- 用单引号包含整个结果字符串;
但是手动执行此操作很乏味且容易出错。
问题
我可以让 Bash 根据需要在整个命令行中正确添加一级单引号/转义吗?
(注意:当我回答这个问题时出现了这个问题。)
解决方案
是的。我的想法是调用一个 shell 函数(在击键时),它将
READLINE_LINE
使用该${variable@Q}
功能进行操作。文档的相关部分:
(来源)
(来源)
以下适用于 Bash 4.4.20:
要测试解决方案,请在命令行中准备一个命令(不要执行),例如
(引用和整个命令可以简化。故意这样。您可以执行它以确保它是有效的命令,但在继续之前将其放回命令行中。)
点击Ctrl+ x,Ctrl+o它将被正确引用/转义以用于我们的目的。它看起来像这样:
现在您需要做的就是在前面添加
watch
(或,或其他)并执行。ssh …
如果是,watch
请注意标题就像它包含原始命令。该命令正确到达
watch
,没有部分被过早解释。改进
为方便起见,请考虑以下变体:
它将准备行并将光标放在开头,因此您可以
watch
立即输入。或者甚至可能是这个变体(它故意使用不同的名称,我们正在为它创建一个单独的绑定):现在Ctrl+ x, Ctrl+w处理引用,
watch
自动插入并将光标放在正确的位置供您键入选项。使用另一个函数
READLINE_POINT
,可以处理以下场景:类型watch
(或ssh …
)后跟命令,其中引用/转义就像要直接执行命令一样。将光标放在命令开始的位置,点击按键,让函数修改从光标到行尾的所有内容。我这里不提供这样的功能;需要的话自己写。Yo Dawg,我听说你喜欢引用
您可以堆叠解决方案。我的意思是你可以离开这个
对此
对此
对此
(是的,我知道
ssh -J
)只需点击Ctrl+ x,Ctrl+o并在每个步骤的前面附加一个或几个单词。