我正在对脚本进行故障排除,我想逐行手动输入每一行以查找错误。
我的脚本有一个 if 语句:
if [ -d dir1 ]; then
rm -rf dir1
fi
所以我试着输入一行命令
$ if [ -d dir1 ]; then rm -rf dir1 fi
>
我尝试了 Ctrl-D 但随后收到消息:bash:语法错误:文件意外结束
那么如何在命令行输入这个if语句呢?
我正在对脚本进行故障排除,我想逐行手动输入每一行以查找错误。
我的脚本有一个 if 语句:
if [ -d dir1 ]; then
rm -rf dir1
fi
所以我试着输入一行命令
$ if [ -d dir1 ]; then rm -rf dir1 fi
>
我尝试了 Ctrl-D 但随后收到消息:bash:语法错误:文件意外结束
那么如何在命令行输入这个if语句呢?
简短回答:您需要在 . 之后加一个分号
rm -rf dir1
。查看实际效果:
if
完全按照脚本中显示的方式输入块:运行后,使用向上箭头回调最后一个命令,它会
if
在一行上显示整个块:shell 需要某种方式来解释 if 块内命令之间的中断。它不能简单地将其视为一次执行的单个命令,因此分号用作这些中断。
除了约翰的回答,这是完全正确的,但仍然会以你输入一个(很长的)单行命令而告终,还有一种输入多行命令的实际方法:
那就是……只是打字。Enter 后,shell 将看到命令未完成并提供“继续提示”。
但是,如果命令实际上是完整的,或者您不想依赖它怎么办?也有可能。
它称为 VLNEXT,通常设置为^V,但如果您想真正确定,请检查
stty -a
输出并lnext
在 cchars 组中查找(在 BSD 上;GNU stty 是一个相当未分类的输出,但对我来说它在第三行)。作为一个额外的复杂性,在熟化模式下,Enter 键提交
^M
(ASCII 0x0D)但我们实际上需要 ASCII 0x0A,^J
所以你必须用 VLNEXT 按下它。然后,我们可以输入
if [ -d dir1 ]; then
^V^Jrm -rf dir1
^V^Jfi
Enter,它将作为一个大命令运行。在 GNU bash中看起来像这样………当按下↑查看历史记录时,您会看到它实际上保存了带有分号的单行表格。
其他 shell 的显示方式可能有所不同——例如,mksh在输入时会这样显示……
......如果你按下↑你会看到它保存它就像在历史中一样。如果按←几次,您会注意到这些
^J
被视为单个字符,因为它实际上是一个控制字符,而不是两个字符^
(插入符号)和J
.因此,GNU bash 将具有更好的输入,但在内部对其进行转换,而 mksh 具有单行输入(和命令行编辑),但将其保留在历史记录中,与输入的完全一样。
在zsh中,输入时看起来像多行 bash……
…这也存储在历史记录中(就像在 mksh 中一样,但是 zsh 具有多行输入编辑功能,因此可以负担得起将光标上下移动,从而将其扩展
^J
为实际的换行符;但这有缺点,尽管, 按下^U
不再杀死整个输入,而是只杀死其中的一个子行)。yash的行为类似于 1999 年的pdksh,因为它
^J
在一行中输入(就像 mksh 一样)但是将每一行单独保存到历史记录中,所以↑你得到的只是最后一个fi
,这可能非常没有帮助。现代(Debian stable/bullseye)破折号在这里表现得像 mksh。
现代 AT&T ksh93 ksh “u+m” 甚至更奇怪:在输入时,它的行为类似于它在 pdksh/mksh 血统中的表兄弟,但是当按下↑它时(仅)获取命令的第一行(而不是像 pdksh 那样的最后一行)做了),这可能也不是很有帮助。
tcsh是……奇怪的。因为^V^J它显示
^M
内联(但除此之外的行为与 mksh 类似,当然,因为它不是 POSIX 兼容的 shell,该if
命令将因语法错误而失败),而对于^V^M和^VEnter,它的行为就像只是按下 Enter 一样。最后,原来的csh ……
......那里没有惊喜。它没有交互式的方式来检索历史记录,并且发出
history
命令以显示已保存的行没有输出(即使是简单的ls
),所以我相信它需要启用一些设置或其他东西(我从未使用过系列C 壳)。全面披露:我是 mksh 开发人员。