我想在 bash 中创建一个交互式 CLI。与 bash 为每行添加前缀的方式类似user@host:~$
,我想为每行添加前缀foobar>
。此功能可以在 Metasploit 或 mysqli 等 CLI 应用程序中看到,但它们使用单独的编程语言,而我只想使用 bash 脚本。此外,我需要向上/向下箭头键来使用该history
功能(或类似的功能),允许用户轻松调出最后一个输入或之前的第 n 个输入。
在尝试创建解决方案时,我遇到了这个答案它允许 bash 解释箭头键并使用 调出最后的输入history
。这很有效,但是我很难将其与行前缀结合起来。我找到了解决方案这里然而,要使用 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 循环之前使用来为 cli 的第一行添加前缀。下面我boop
在第一行输入,echo 的输出被重定向到我的 coproc。然而,在此之后,使用向上箭头将输入带回boop
将打印boop
没有我的前缀(如最后一行所示)。
$ ./test.sh
foobar> boop
foobar> boop
boop
我确实意识到,因为我在循环内没有 printf,所以我正在输入的行在第一次迭代后不会添加前缀。我可以稍后通过重新处理循环来解决这个问题(尽管我担心将前缀行发送到前缀 coproc,从而实现双重前缀)。我主要需要修复的是向上箭头输出不是获得前缀。我假设该信息是通过 发送的stdout
,但显然不是。我也尝试过stderr
以相同的方式重定向,但这会阻止终端在我键入时回显我键入的内容。
我需要一个解决方案来为 bash 脚本中的每一行添加前缀,无论它是基于我上面提供的脚本构建的还是使用不同的方法。我还希望它尽可能优雅,因为我将使用这种技术构建一个 CLI 工具,并且希望尽可能少的额外开销。我认为重定向可以为我做到这一点,但显然它比我最初想象的要复杂。
答案1
我并没有真正关注这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
基本思想借鉴自这个问题。