我希望有一个bash脚本来实现bash命令行本身的一些功能:即命令历史记录和vi样式的命令编辑。
脚本将永远循环(直到crtl / d)并从终端中的用户读取输入,将每行视为命令。这些命令实际上是我已编写的一组shell脚本,旨在支持照片工作流程。在此解释环境中应该可以使用相同的编辑和调用功能。
非常需要在此脚本中使用bash命令历史记录和命令编辑功能。
答案 0 :(得分:0)
在寻找一种也可以在脚本中模拟命令历史记录的方法时,由于在网上找不到太多内容,因此自己创建了一个简单的脚本。可能不完全是您的要求,但可能会给您或其他人一些参考。
这实际上只是一个大功能,除了处理诸如行为之类的提示并按Enter返回屏幕上的字符串外,别无其他。它允许浏览指定的历史文件,同时保存新的输入以返回。自动缩进或移动标记不在下面实现。我认为该脚本需要带有算术shell的bash版本4,但是更改为较旧的语法,bash 3应该可以工作。还没有完全测试。
用作:
./scriptname.sh /optional/path/to/history_file
脚本
#!/bin/bash
# vim: ts=4:
function getInput() {
local hist_file="${1:-.script_hist}";
local result="";
local escape_char=$(printf "\u1b")
local tab=$(echo -e "\t");
local backspace=$(cat << eof
0000000 005177
0000002
eof
);
local curr_hist=0;
local curr_cmd="";
function browseHistory() {
! test -s "$hist_file" && return 1;
local max_hist="$(cat "$hist_file" | wc -l || echo 0)";
curr_hist=$((curr_hist + "$1"));
(( curr_hist > max_hist )) && curr_hist=$max_hist;
if (( curr_hist <= 0 )); then
curr_hist=0;
return 1;
fi
result="$(sed -n "$((max_hist - curr_hist + 1))p" < "$hist_file")";
return 0;
}
ifs=$IFS;
while true; do
# empty IFS, read one char
IFS= read -rsn1 input
if [[ $input == $escape_char ]]; then
# read two more chars, this is for non alphanumeric input
read -rsn2 input
fi
# check special case for backspace or tab first
# then move onto arrow keys or anything else in case
if [[ $(echo "$input" | od) = "$backspace" ]]; then
# delete last character of current on screen string
result=${result%?};
elif [ "$input" = "$tab" ]; then
# replace with function call for autofill or something
# it's unused but added in case it would be useful later on
continue;
else
case $input in
'[A')
! browseHistory '1' && result=$curr_cmd;
;;
'[B')
! browseHistory '-1' && result=$curr_cmd;
;;
'[D') continue ;; # left, does nothing right now
'[C') continue ;; # right, this is still left to do
*)
# matches enter and returns on screen string
[[ "$input" == "" ]] && break;
result+=$input
;;
esac
fi
# store current command, for going back after browsing history
(( curr_hist == 0 )) && curr_cmd="$result";
echo -en "\r\033[K";
echo -en "${result}"
done
IFS=$ifs;
test -n "$result" && echo "$result" >> "$hist_file";
return 0;
}
getInput $1