-1

在一个人为的例子中,如果我有以下内容:

sup="$(printf "\e[s" > /dev/tty; printf "one" > /dev/tty; printf "\e[u\e[Jtwo" > /dev/tty)"

输出将成功擦除one,只留下:

two

但是,如果我用echo "one"它来打印换行符:

sup="$(printf "\e[s" > /dev/tty; echo "one" > /dev/tty; printf "\e[u\e[Jtwo" > /dev/tty)"

然后输出是:

one
two

为什么换行符会破坏光标处理?我怎么能解决它?

一个更全面的例子是:

sup="$(printf "\e[s" > /dev/tty; for (( i=0; i<5; i++)); do echo -e "a random number is:\n$RANDOM" > /dev/tty; sleep 1; printf "\e[u\e[J" > /dev/tty; done; echo 'result')"
echo "sup=$sup" # sup=result
4

2 回答 2

1

我怀疑您正在写入窗口的最后一行。写入换行符将导致窗口内容滚动。当您使用 恢复光标位置时ESC [ u,它会返回到使用 保存的窗口中的物理位置,而ESC [ s不是滚动缓冲区中的位置。但是这个词one会向上滚动一行,所以two会写到它之后的行而不是覆盖它。

于 2021-09-10T15:29:15.690 回答
0

正如@Barmer回答所暗示的那样,恢复游标不起作用的原因是保存游标只保存左/右页边距,而不是行:

在 SCO 控制台模式下保存光标位置/状态。[22] 在垂直分屏模式下,改为用于设置(如 CSI n ; ns)或重置左右边距。 [23] https://en.wikipedia.org/wiki/ANSI_escape_code#CUP

我能够想出一个不需要我计算行号的便携式解决方案。

tty.bash

#!/usr/bin/env bash

# sourced from:
# https://stackoverflow.com/a/69138082/130638
# inspired by:
# https://unix.stackexchange.com/a/88304/50703
# https://stackoverflow.com/a/2575525/130638
# https://askubuntu.com/a/366158/22776
# https://stackoverflow.com/a/5810220/130638
get_tty_snapshot () {
    local pos oldstty y x y_offset="${1:-0}" x_offset="${2:-0}"
    exec < /dev/tty
    oldstty=$(stty -g)
    stty raw -echo min 0
    echo -en "\e[6n" > /dev/tty
    IFS=';' read -r -d R -a pos
    stty "$oldstty"
    y="$((${pos[0]:2} - 2 + y_offset))"
    x="$((pos[1] - 1 + x_offset))"
    echo -en "\e[${y};${x}H\e[J"
}
use_tty_snapshot () {
    echo -en "$1" > /dev/tty
}

embed.bash

#!/usr/bin/env bash
source "./tty.bash"

tty_snapshot="$(get_tty_snapshot)"

for (( i=0; i<5; i++)); do
    echo -e "one random number $RANDOM\nanother random number: $RANDOM" > /dev/tty
    sleep 1
    use_tty_snapshot "$tty_snapshot"
done

echo 'result'

example.bash

#!/usr/bin/env bash

echo "ask result"
result="$(./test-cursor-embed)"
echo "got result=[$result]"
于 2021-09-10T21:16:14.593 回答