我想在bash中创建一个交互式CLI。类似于bash在每一行前面加上 [email protected]:~$ ,我想在每一行前加上 foobar> . 这种功能可以在诸如Metasploit或mysqli的CLI应用程序中看到,但是它们使用不同的编程语言,而我只想使用bash脚本。另外,我需要上/下箭头键来使用 history 功能(或类似的功能),允许用户轻松地显示最后一个输入或之前的第n个输入。

在尝试创建解决方案时,我遇到了 this answer 它允许bash解释箭头键并使用 history . 这很好,但是我很难把它和线前缀结合起来。我找到了解决办法 here 但是,要使用coproc预处理stdout并实现它的一个版本,此方法既不适用于您正在键入的输入行,也不适用于使用带有 history . 我目前掌握的bash脚本如下:

exec 4>&1
coproc out (sed 's/^/foobar> /' >&4)
exec 1>&${out[1]}

printf "foobar> " >&4
while read -e x; do
   history -s "$x"
   echo $x
done

下面是详细说明这两个问题的输出。如下所示,我可以使用 printf "foobar> " >&4 在while循环之前的上面脚本中。I型以下 boop 在第一行,echo的输出被重定向到我的coproc。但是在此之后,使用向上箭头将输入 boop 背面将打印 boop 没有我的前缀(如最后一行所示)。

$ ./test.sh
foobar> boop
foobar> boop
boop

我确实意识到,因为循环中没有printf,所以在第一次迭代之后,我正在键入的行不会有前缀。我可以通过修改循环来修复这个问题(尽管我担心将前缀行发送到前缀COPROC,因此双前缀)。我主要需要修复的是上箭头输出没有前缀。我以为这些信息是通过 stdout ,但显然不是。我试过重定向 stderr 同样的方式,但这会阻止终端在我输入时回显我输入的内容。

我需要一个解决方案来对BASH脚本中的每一行进行预处理,无论是建立在上面提供的脚本还是使用不同的方法。我也希望它尽可能优雅,因为我将使用此技术构建一个CLI工具,并且希望尽可能少的额外开销。我原以为重定向可以帮我做到这一点,但显然它比我最初想象的要复杂。

注:如果历史文件不使用,它如何通过箭头键将其内容打印到屏幕上 stdout ? 在终端屏幕上放置文本使用什么?

最佳回复

我不是真的在跟踪这个 coproc 事情。对你来说 read -p 看起来不错。您可能需要使用一个单独的(非默认)历史文件。

警告:脚本创建/使用 $HOME/.custom_history 为了保存它的历史。测试解决方案后,手动删除文件。

#!/bin/bash

# History management
hfile="$HOME/.custom_history"
HISTCONTROL=ignoreboth
history -r "$hfile"
trap 'history -a "$hfile"' exit

# Main loop
while read -ep 'foobar> ' x; do
   history -s -- "$x"
   printf '%s\n' "$x"
done

基本思想借鉴 this question .