стирание терминального вывода на Linux

Я писал программу командной строки, которая будет иметь строку состояния, во многом как wget.

Основная проблема, с которой я сталкиваюсь: как я удаляю то, что я уже отправил в stdout/stderr?

Я имел на идее: используйте символ клавиши Backspace '\b' и сотрите вывод, который я отправил. Это - лучший способ? Действительно ли это - единственный путь? Существует ли лучший путь?

PS: Я не хочу использовать что-либо как ncurses. Простой C.

Спасибо


Править:

Я могу также подняться и/или вниз? Пример: у Меня есть 10 строк вывода, я хочу изменить 3-ю строку от Doing ABC кому: ABC: Done. Как я могу сделать это?

Кроме того, кто-либо может отправить больше деталей о том, каковы символы VT102? Каковы его возможности? Отправьте хорошие ссылки на это, если у Вас есть кто-либо.

Спасибо

7
задан jrharshath 5 February 2010 в 15:26
поделиться

7 ответов

Используйте '\ r', чтобы вернуться в начало строки и, возможно, переписать всю строку.

Ищите управляющие последовательности VT102 - это последовательности символов ESC ... для управления вашим терминалом.

3
ответ дан 6 December 2019 в 11:49
поделиться

Основные управляющие символы форматирования - это возврат (\ b), табуляция (\ t), новая строка (\ n) и возврат каретки (\ r ). Если вам нужно больше, вы можете использовать escape-последовательности ANSI X3.64 / ISO / IEC 6429 / ECMA-48 ; по крайней мере подмножество VT100 распознается большинством современных терминалов и эмуляторов. Преимущество использования ncurses заключается в том, что он будет искать возможности вашего конкретного терминала, и поэтому он будет работать, даже если ваш терминал использует другой набор управляющих последовательностей.

6
ответ дан 6 December 2019 в 11:49
поделиться

Вы должны помнить, что что касается обычных подпрограмм stdio, stdout - это просто поток байтов без присущих характеристик отображения ; это зависит от целевого устройства, которым может быть что угодно, от обычного терминала в стиле VT100 до терминала для печатных копий, листового принтера и плоттера и т. д.

IMO, вам гораздо лучше использовать библиотеку вроде ncurses , чем пытаться собрать свой собственный код управления дисплеем с escape-кодами VT100, даже для относительно простой задачи вроде это. Я знаю, что вы хотите придерживаться "старого доброго Си", но эта задача выходит за рамки старого доброго Си.

5
ответ дан 6 December 2019 в 11:49
поделиться

Небольшое изменение вашего собственного решения:

Вы также можете напечатать возврат каретки ( \ r ), который вернет вас в начало строки.

1
ответ дан 6 December 2019 в 11:49
поделиться

Профилировщик Hibernate Profiler может генерировать динамические отчеты из статистики времени выполнения Hibernate. Генерируются различные предупреждения, такие как предупреждение о SELECT N + 1.

Его можно использовать в системе непрерывной интеграции.

-121--4481922-

Я держу свои приложения на краю 2,3, но поскольку в 3 году есть много фундаментальных изменений в Rails, я, вероятно, установлю бета-версию, поработаю над их преобразованием и надеюсь быть готовым к моменту выхода в качестве стабильного.

Я также рад, что есть много времени перед RailsConf, так что я действительно могу познакомиться с новыми функциями Rails 3 и не буду чувствовать себя потерянным/перегруженным там.

-121--3653480-

Это индикатор прогресса для bash.

function gauge()
{
        progress="$1"
        total="$2"
        width=`tput cols`
        let gwidth=width-7

        if [ "$total" == "0" ]; then
                percent=100
        else
                set +e
                let percent=progress*100/total;
                set -e
        fi

        set +e
        let fillcount=percent*gwidth/100
        let nofillcount=gwidth-fillcount
        set -e

        fill="";
        if [ "$fillcount" -gt "0" ]; then
                for i in `seq $fillcount`; do
                        fill="$fill""|"
                done
        fi;
        nofill=""
        if [ "$nofillcount" -gt "0" ]; then
                for i in `seq $nofillcount`; do
                        nofill="$nofill"" ";
                done
        fi
        echo -e -n "\r[""$fill""$nofill""] ""$percent""%";
}
0
ответ дан 6 December 2019 в 11:49
поделиться

О индикаторе прогресса: что-то вроде этого?

#include <stdio.h>
#include <unistd.h>

typedef enum
{
    false=0,
    true=!false
} bool;

typedef struct
{
    /* Start delimiter (e.g. [ )*/
    char StartDelimiter;
    /* End Delimiter (e.g. ] )*/
    char EndDelimiter;
    /* Central block (e.g. = )*/
    char Block;
    /* Last block (e.g. > ) */
    char CurBlock;
    /* Width of the progress bar (in characters) */
    unsigned int Width;
    /* Maximum value of the progress bar */
    double Max;
    /* True if we have to print also the percentage of the operation */
    bool PrintPercentage;
    /* True if the bar must be redrawn;
       note that this must be just set to false before the first call, the function then will change it by itself.  */
    bool Update;
} ProgressBarSettings;

/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings);
/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings);

int main()
{
    int i;
    /* Init the bar settings */
    ProgressBarSettings pbs;
    DefaultProgressBar(&pbs);
    pbs.Max=200;
    pbs.Width=60;
    printf("Progress: ");
    /* Show the empty bar */
    PrintProgressBar(0,&pbs);
    for(i=0;i<=pbs.Max;i++)
    {
        /* Wait 50 msec */
        usleep(50000);
        /* Update the progress bar */
        PrintProgressBar(i,&pbs);
    }
    puts(" Done");
    return 0;
}

/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings)
{
    Settings->StartDelimiter='[';
    Settings->EndDelimiter=']';
    Settings->Block='=';
    Settings->CurBlock='>';
    Settings->PrintPercentage=true;
    Settings->Update=false;
    Settings->Max=100;
    Settings->Width=40;
}

/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings)
{
    /* Blocks to print */
    unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max);
    /* Counter */
    unsigned int counter;
    /* If we are updating an existing bar...*/
    if(Settings->Update)
    {
        /* ... we get back to its first character to rewrite it... */
        for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--)
            putchar('\b');
    }
    else
        Settings->Update=true; /* next time we'll be updating it */
    /* Print the first delimiter */
    putchar(Settings->StartDelimiter);
    /* Reset the counter */
    counter=Settings->Width;
    /* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have
       the number of spaces to fill the bar */ 
    for(;printBlocks>1;printBlocks--,counter--)
        putchar(Settings->Block);
    /* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */
    putchar((Settings->Max==Pos)?Settings->Block:Settings->CurBlock);
    /* Another block was printed, decrement the counter */ 
    counter--;
    /* Fill the rest of the bar with spaces */
    for(;counter;counter--)
        putchar(' ');
    /* Print the end delimiter */
    putchar(Settings->EndDelimiter);
    /* If asked, print also the percentage */
    if(Settings->PrintPercentage)
        printf(" %3d%%",(int)(100*Pos/Settings->Max));
    /* Flush the output buffer */
    fflush(stdout);
};

Обратите внимание: unistd.h и usleep - это просто симулирование прогресса операции, сам индикатор прогресса использует стандартную библиотеку. Его единственное предположение о выходном потоке заключается в том, что \b фактически попадает в предыдущий написанный символ. Я успешно пробовал его на Windows и Linux (с gnome-терминалом), не знаю, корректно ли он работает с некоторыми терминальными эмуляторами. Извините за излишнее количество комментариев, я написал его для другого форума, где мне нужно было прагматично объяснить каждую строчку кода новичку на Си.

0
ответ дан 6 December 2019 в 11:49
поделиться

Также есть возможность использовать Ncurses , который является библиотекой для текстового пользовательского интерфейса. , где такое поведение должно иметь некоторую поддержку. Однако для чего-то вроде этого это может быть излишним.

2
ответ дан 6 December 2019 в 11:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: