使用Bash脚本开发简易文本编辑器:实现上下箭头移动功能求助
实现Bash文本编辑器的上下箭头移动功能
嘿,很高兴帮你解决这个问题!你的代码已经把文本内容读到数组arr里了,接下来要实现上下箭头移动,核心是跟踪光标位置+处理终端的特殊按键输入——因为上下箭头在终端里是特殊的转义序列,不是普通字符,咱们一步步来:
核心思路
- 用变量记录当前光标所在的行号和列号(比如
current_row和current_col)。 - 禁用终端的默认回显和缓冲,这样输入的箭头键不会直接显示在屏幕上,而且能实时捕获按键。
- 识别上下箭头的转义序列:上箭头是
\e[A,下箭头是\e[B,读取时要判断这个组合。 - 每次移动后重新绘制整个文本,标记出当前光标的位置。
完整示例代码
#!/bin/bash # 初始化变量:存储文本的数组,当前行、列号 declare -a arr current_row=0 current_col=0 # 读取初始文本到数组 echo "请输入文本(按Ctrl+D结束输入):" while read -re; do arr+=( "$REPLY" ) done # 如果数组为空,添加一行空内容避免报错 if [ ${#arr[@]} -eq 0 ]; then arr=( "" ) fi # 退出时恢复终端设置(非常重要!) trap 'stty echo icanon; clear; exit' EXIT INT # 禁用终端回显和缓冲,实时捕获按键 stty -echo -icanon # 主循环:处理按键输入 while true; do # 清屏后重新绘制文本 clear for i in "${!arr[@]}"; do line="${arr[$i]}" if [ $i -eq $current_row ]; then # 高亮当前行,并用[]标记光标位置(也可以用反向显示) if [ $current_col -eq 0 ]; then echo "[${line:0:1}]${line:1}" elif [ $current_col -ge ${#line} ]; then echo "${line}[]" else echo "${line:0:$current_col}[${line:$current_col:1}]${line:$((current_col+1))}" fi else echo "$line" fi done # 读取一个按键 read -n 1 key # 判断是否是Esc开头的转义序列(箭头键) if [ "$key" = $'\e' ]; then # 再读后面两个字符 read -n 2 seq case "$seq" in "[A") # 上箭头 if [ $current_row -gt 0 ]; then current_row=$((current_row-1)) # 调整列号:不超过当前行的长度 max_col=${#arr[$current_row]} if [ $current_col -gt $max_col ]; then current_col=$max_col fi fi ;; "[B") # 下箭头 if [ $current_row -lt $(( ${#arr[@]} - 1 )) ]; then current_row=$((current_row+1)) # 调整列号:不超过当前行的长度 max_col=${#arr[$current_row]} if [ $current_col -gt $max_col ]; then current_col=$max_col fi fi ;; "[C") # 右箭头(补充实现,你可能已经有了) max_col=${#arr[$current_row]} if [ $current_col -lt $max_col ]; then current_col=$((current_col+1)) fi ;; "[D") # 左箭头(补充实现) if [ $current_col -gt 0 ]; then current_col=$((current_col-1)) fi ;; esac elif [ "$key" = $'\x03' ]; then # Ctrl+C退出 exit 0 fi done
代码解释
- 终端设置:
stty -echo -icanon关闭回显和规范模式,让我们能直接捕获每个按键;trap确保脚本退出时恢复终端默认设置,不然你的终端会变得奇怪! - 光标位置调整:上下移动时,要检查是否在数组的边界内(不能移到第一行上面或最后一行下面),同时列号不能超过当前行的长度,避免光标跑到空位置。
- 文本绘制:每次循环都清屏重绘,当前行用
[]标记光标位置,你也可以改成终端的反向显示(比如用\e[7m和\e[0m包裹光标处的字符),效果更像真实编辑器。
你可以直接运行这个脚本,先输入几行文本,然后用上下左右箭头试试,完美实现移动功能!
内容的提问来源于stack exchange,提问作者Michu




