Очистить вывод CLI CLI

Я пытаюсь получить индикатор "живого" прогресса, работающий над моим приложением php CLI. Вместо вывода

1Done
2Done
3Done

Я бы предпочел, чтобы он очистился и просто показал последний результат. system ( "command\C CLS" ) не работает. Также не ob_flush(), flush() или что-нибудь еще, что я нашел.

Я запускаю Windows 7 64 бит, я заметил, что вывод командной строки в реальном времени был неожиданным. Все предупреждали меня, что это не так... но это... 64-битный перк?

Приветствия за помощь!

Я хочу избежать повторения 24 новых строк, если смогу.

Ответ 1

Попробуйте вывести строку текста и завершите ее с помощью "\ r" вместо "\n".

Символ "\n" является строкой, которая переходит к следующей строке, но "\ r" - это просто возврат, который возвращает курсор в позицию 0 в той же строке.

Итак, вы можете:

echo "1Done\r";
echo "2Done\r";
echo "3Done\r";

и др.

Обязательно выведите пробелы перед "\ r" , чтобы очистить предыдущее содержимое строки.

[Изменить] Дополнительно: Заинтересованы в некоторых историях и истории? В Wikipedia есть хорошие статьи о "\n" (фид строки) и "\ r" (возврат каретки)

Ответ 2

Я столкнулся с этим при поиске многолинейного решения этой проблемы. Это то, что я в итоге придумал. Вы можете использовать команды Ansi Escape. http://www.inwap.com/pdp10/ansicode.txt

<?php
function replaceOut($str)
{
    $numNewLines = substr_count($str, "\n");
    echo chr(27) . "[0G"; // Set cursor to first column
    echo $str;
    echo chr(27) . "[" . $numNewLines ."A"; // Set cursor up x lines
}

while (true) {
    replaceOut("First Ln\nTime: " . time() . "\nThird Ln");
    sleep(1);
}
?>

Ответ 3

Недавно я написал функцию, которая также будет отслеживать количество строк, которые она выдает последним, поэтому вы можете кормить произвольную длину строки, с символами новой строки, и она заменит последний вывод текущим.

С массивом строк:

$lines = array(
    'This is a pretty short line',
    'This line is slightly longer because it has more characters (i suck at lorem)',
    'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
    "This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
    "one\nmore\nwith\nnewlines",
    'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
    "This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
    'This is a pretty short line',
);

Можно использовать следующую функцию:

function replaceable_echo($message, $force_clear_lines = NULL) {
    static $last_lines = 0;

    if(!is_null($force_clear_lines)) {
        $last_lines = $force_clear_lines;
    }

    $term_width = exec('tput cols', $toss, $status);
    if($status) {
        $term_width = 64; // Arbitrary fall-back term width.
    }

    $line_count = 0;
    foreach(explode("\n", $message) as $line) {
        $line_count += count(str_split($line, $term_width));
    }

    // Erasure MAGIC: Clear as many lines as the last output had.
    for($i = 0; $i < $last_lines; $i++) {
        // Return to the beginning of the line
        echo "\r";
        // Erase to the end of the line
        echo "\033[K";
        // Move cursor Up a line
        echo "\033[1A";
        // Return to the beginning of the line
        echo "\r";
        // Erase to the end of the line
        echo "\033[K";
        // Return to the beginning of the line
        echo "\r";
        // Can be consolodated into
        // echo "\r\033[K\033[1A\r\033[K\r";
    }

    $last_lines = $line_count;

    echo $message."\n";
}

В цикле:

foreach($lines as $line) {
    replaceable_echo($line);
    sleep(1);
}

И все линии заменяют друг друга.

Название функции может использовать некоторую работу, просто взбивает ее, но идея звучит. Подайте его (int) как второй параметр, и он заменит это множество строк выше. Это было бы полезно, если бы вы печатали после другого вывода, и вы не хотели бы заменять неправильное количество строк (или любой, дать ему 0).

Не знаю, казалось хорошим решением для меня.

Я уверен, что эхо закончит новую строку так, чтобы она позволяла пользователю по-прежнему использовать echo/print_r, не убивая строку (используйте переопределение, чтобы не удалять такие выходы), и командная строка вернется в правильное место.

Ответ 4

function clearTerminal () {
  DIRECTORY_SEPARATOR === '\\' ? popen('cls', 'w') : exec('clear');
}

Протестировано на Win 7 PHP 7. Решение для Linux должно работать, согласно сообщениям других пользователей.

Ответ 5

что-то вроде этого:

for ($i = 0; $i <= 100; $i++) {
    echo "Loading... {$i}%\r";
    usleep(10000);
}

Ответ 6

я знаю, что вопрос не только в том, как очистить одну строку в PHP, но это лучший результат Google для "clear line cli php", поэтому вот как очистить одну строку:

function clearLine()
{
    echo "\033[2K\r";
}

Ответ 7

Функции консоли зависят от платформы, и поэтому у этого PHP нет встроенных функций для решения этой проблемы. system и другие подобные функции не будут работать в этом случае, потому что PHP фиксирует вывод этих программ и печатает/возвращает их. То, что печатает PHP, идет на стандартный вывод, а не непосредственно на консоль, поэтому "печать" вывода cls не будет работать.

Ответ 8

<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);

function bufferout($newline, $buffer=null){
    $count = strlen(rtrim($buffer));
    $buffer = $newline;
    if(($whilespace = $count-strlen($buffer))>=1){
        $buffer .= str_repeat(" ", $whilespace);
    }
    return $buffer."\r"; 
};

$start = "abcdefghijklmnopqrstuvwxyz0123456789";
$i = strlen($start);

while ($i >= 0){
    $new = substr($start, 0, $i);
    if($old){
        echo $old = bufferout($new, $old);
    }else{
        echo $old = bufferout($new);
    }
    sleep(1);
    $i--;
}
?>

Простая реализация ответа @dkamins. Это работает хорошо. Это бит-хаш. Но делает работу. Не работает через несколько строк.

Ответ 9

Используйте эту команду для очистки кли:

echo chr(27).chr(91).'H'.chr(27).chr(91).'J';   //^[H^[J