Как стереть печатные символы в консольном приложении (Linux)?

Я создаю небольшое консольное приложение, которому нужен индикатор выполнения. Что-то вроде...

Conversion: 175/348 Seconds   |==========          |  50%

Мой вопрос: как стереть символы, уже напечатанные на консоли? Когда я достигаю 51-го процента, я должен стереть эту строку из консоли и вставить новую строку. В моем текущем решении это то, что происходит...

Conversion: 175/348 Seconds   |==========          |  50%
Conversion: 179/348 Seconds   |==========          |  52%
Conversion: 183/348 Seconds   |==========          |  54%
Conversion: 187/348 Seconds   |===========         |  56%

Я использую код...

print "Conversion: $converted_seconds/$total_time Seconds   $progress_bar  $converted_percentage%\n";

Я делаю это в Linux, используя PHP (только я буду использовать приложение, так что извините за выбор языка). Таким образом, решение должно работать на платформе Linux, но если у вас есть кроссплатформенное решение, это было бы предпочтительнее.


person Binny V A    schedule 10.01.2009    source источник


Ответы (6)


Я не думаю, что вам нужно извиняться за выбор языка. PHP — отличный язык для консольных приложений.

Попробуйте это:

<?php
for( $i=0;$i<10;$i++){
  print "$i \r";
  sleep(1);
}
?>

«\r» перезапишет строку новым текстом. Чтобы создать новую строку, вы можете просто использовать "\n", но я предполагаю, что вы уже это знали.

Надеюсь это поможет! Я знаю, что это работает в Linux, но я не знаю, работает ли это в Windows или других операционных системах.

person GnomeCubed    schedule 10.01.2009
comment
Кроме того, многие тупые терминалы (или эмуляторы терминалов, или режимы мозгового мертвого буфера кадров) будут сбиты с толку этим, как и различные SSH-клиенты. Буквальный backspace '\b' - самый безопасный способ. - person Tim Post♦; 10.01.2009
comment
Я совершенно забыл, что вы могли сделать это в оболочке. - person David; 10.01.2009
comment
Ух ты! Я собираюсь попробовать это. Добавлю несколько цветов, чтобы увидеть, работает ли это - person Viet; 15.11.2012
comment
@GnomeCubed PHP никогда не следует использовать. - person Nick Sotiros; 07.04.2018

Чтобы стереть ранее напечатанный символ, у вас есть три варианта:

  • echo chr(8) . " "; повторяет символ возврата и перемещает курсор на одну позицию назад, после чего пробел перезаписывает символ. Вы можете использовать chr(8) несколько раз подряд, чтобы вернуться на несколько символов.

  • echo "\r"; вернет курсор в начало текущей строки. Теперь вы можете заменить строку новым текстом.

  • Третий вариант — установить строку и столбец положения курсора с помощью escape-кодов ANSI, а затем распечатать замещающие символы. Это может работать не со всеми терминалами:

  function movecursor($line, $column){
      echo "\033[{$line};{$column}H";
  }
person Luna    schedule 08.05.2010

\r сделал свое дело.

Для дальнейшего использования \b не работает в PHP в Linux. Мне было любопытно, поэтому я провел пару экспериментов и на других языках (я делал это в Linux, не знаю, будет ли результат таким же в Windows/Mac).

\b Работает в...

  • Перл
  • Рубин
  • Tcl - с кодом puts -nonewline "Hello\b"

\b Не работает в

  • PHP - код print "Hello\b"; выводит Hello\b
  • Код Python print "Hello\b" выводит Hello<new line> . Тот же результат с print "Hello\b",
person Community    schedule 10.01.2009
comment
python print добавляет \n автоматически. используйте sys.stdout.wirte вместо print, если хотите остаться на той же строке - person Matus; 09.04.2011
comment
Символ возврата, конечно, все еще существует! Он просто недоступен в строковых литералах с escape-последовательностью. Попробуйте chr(8). - person Luna; 15.11.2012

Я не уверен, что это то же самое в Linux, но в консольных приложениях Windows вы можете напечатать \r, и курсор вернется в первую левую позицию строки, что позволит вам перезаписать все символы справа.

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

person Spencer Ruport    schedule 10.01.2009

Кажется, это довольно старая тема, но я добавлю свои 5.

for ($i; $i<_POSITION_; $i--) {
   echo "\010"; //issue backspace 
}

Нашла давно в инете, к сожалению не помню где. Таким образом, все кредиты принадлежат оригинальному автору.

person zergussino    schedule 14.10.2012

чтобы стереть ранее напечатанный символ, я печатаю после него пробел: print "a" print "\b"

напечатает ничего (на самом деле напечатает, а затем заменит пробел, но вы, вероятно, этого не заметите)

person Community    schedule 10.01.2009