Bash - Clearing the last output correctly

后端 未结 2 974
隐瞒了意图╮
隐瞒了意图╮ 2021-01-13 05:53

I\'m trying to create an update-able progress status. In order to do that, I need to be able to clear the last output in its entirety so that I can update it. Carriage retur

相关标签:
2条回答
  • 2021-01-13 06:06

    Something tricky

    Inspired by How to get the cursor position in bash?

    #!/bin/bash
    
    lineformat="This is a very long line with a lot of stuff so they will take " 
    lineformat+="more than standard terminal width (80) columns... Progress %3d%%" 
    
    n=0
    while [[ $n -ne 100 ]]; do
        n=$((n+1))
        printf -v outputstring "$lineformat" $n
        twidth=$(tput cols)      # Get terminal width
        theight=$(tput lines)    # Get terminal height
        oldstty=$(stty -g)       # Save stty settings
        stty raw -echo min 0     # Suppres echo on terminal
        # echo -en "\E[6n"
        tput u7                  # Inquire for cursor position
        read -sdR CURPOS         # Read cursor position
        stty $oldstty            # Restore stty settings
        IFS=\; read cv ch <<<"${CURPOS#$'\e['}" # split $CURPOS
        uplines=$(((${#outputstring}/twidth)+cv-theight))
        ((uplines>0)) &&
            tput cuu $uplines    # cursor up one or more lines
        tput ed                  # clear to end of screen
        tput sc                  # save cursor position
        echo -n "$outputstring"
        tput rc                  # restore cursor
        sleep .0331s
    done
    echo
    

    As tput cols and tput lines is initiated at each loop, you could resize window while running, cuu argument will be re-computed.

    More complex sample

    • Using trap WINCH for querying terminal size only when window is resized
    • Addind newlines for scrolling up before cuu
    • Reducing forks to tput

    There:

    #!/bin/bash
    
    lineformat="This is a very long line with a lot of stuff so they will take " 
    lineformat+="more than standard terminal width (80) columns... Progress %3d%%" 
    
    getWinSize() {
        {
            read twidth
            read theight
        } < <(
            tput -S - <<<$'cols\nlines'
        )
    }
    trap getWinSize WINCH
    getWinSize
    
    getCpos=$(tput u7)
    getCurPos() {
        stty raw -echo min 0
        echo -en "$getCpos"
        read -sdR CURPOS
        stty $oldstty
        IFS=\; read curv curh <<<"${CURPOS#$'\e['}"
    }
    oldstty=$(stty -g)
    
    before=$(tput -S - <<<$'ed\nsc')
    after=$(tput rc)
    n=0
    while [[ $n -ne 100 ]]; do
        n=$((n+1))
        printf -v outputstring "$lineformat" $n
        getCurPos
        uplines=$(((${#outputstring}/twidth)+curv-theight))
        if ((uplines>0)) ;then
            printf -v movedown "%${uplines}s" ''
            echo -en "${movedown// /\\n}"
            tput cuu $uplines
        fi
        printf "%s%s%s" "$before" "$outputstring" "$after"
        sleep .05
    done
    
    downlines=$((${#outputstring}/twidth))
    printf -v movedown "%${downlines}s" ''
    echo "${movedown// /$'\n'}"
    
    0 讨论(0)
  • 2021-01-13 06:16

    Yes, but it is not easy.

    Your first and best options is ANSI Escape sequences and you can control cursor by this codes.

    For compatibility of your script with everyone else's Terminal you should calculate the width / height of that Terminal.
    Here using Xwininfow you can check yours

    wininfo | egrep -e Wid+ -e H+ -e A+
    

    and the output for me will be:

      Absolute upper-left X:  0
      Absolute upper-left Y:  45
      Width: 1600
      Height: 855
    

    Then in your script based on width / height you should update the cursor position or clear unused text on Terminal.

    As user1934428 commented we have a better option by enabling two global variables using shopt (= shell options)

    >>> shopt | grep win
    checkwinsize    on
    

    it is on so we can use them

    >> echo $LINES
    56
    >> echo $COLUMNS
    228
    

    NOTE that such a task by python is much easier to do than using bash

    0 讨论(0)
提交回复
热议问题